diff --git a/eng/pipelines/templates/steps/build-test.yml b/eng/pipelines/templates/steps/build-test.yml index 536460220177..168bdaf09a58 100644 --- a/eng/pipelines/templates/steps/build-test.yml +++ b/eng/pipelines/templates/steps/build-test.yml @@ -86,4 +86,3 @@ steps: codeCoverageTool: Cobertura summaryFileLocation: '${{parameters.GoWorkspace}}sdk/coverage.xml' additionalCodeCoverageFiles: '${{parameters.GoWorkspace}}sdk/coverage.html' - failIfCoverageEmpty: true diff --git a/sdk/arm/compute/2019-12-01/armcompute/go.mod b/sdk/arm/compute/2019-12-01/armcompute/go.mod index 4fa9ef4c4ed3..d84f717ac24a 100644 --- a/sdk/arm/compute/2019-12-01/armcompute/go.mod +++ b/sdk/arm/compute/2019-12-01/armcompute/go.mod @@ -5,11 +5,9 @@ go 1.13 require ( github.com/Azure/azure-sdk-for-go/sdk/arm/network/2020-03-01/armnetwork v0.0.0-00010101000000-000000000000 github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.0.0-00010101000000-000000000000 + github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0 ) -replace github.com/Azure/azure-sdk-for-go/sdk/azidentity => ../../../../azidentity - replace github.com/Azure/azure-sdk-for-go/sdk/arm/network/2020-03-01/armnetwork => ../../../network/2020-03-01/armnetwork diff --git a/sdk/arm/compute/2019-12-01/armcompute/go.sum b/sdk/arm/compute/2019-12-01/armcompute/go.sum index 0d2a0bcb2b8e..9155ce0e045b 100644 --- a/sdk/arm/compute/2019-12-01/armcompute/go.sum +++ b/sdk/arm/compute/2019-12-01/armcompute/go.sum @@ -1,12 +1,15 @@ github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0 h1:i4/txgB7gpzLa3YBBPnSSXnRB5+oOd+79M3EhlaaEHM= github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0/go.mod h1:/cH2D+NpD2KRgnop4cU+S5P2On5mP6KWgpWq48+Bt/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0 h1:ogZVkNX3wS6ekWS3hD9sQCghWIGfw8CQ9JKv0rQQlVw= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0/go.mod h1:UKq2za3CMGx75vfPM9tPSuTBNODR4hX1qAeb+GRoDkc= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 h1:VdhfbVpQ3dkhXYOx/Wj1+utikcZkZSZSmpqmXWwaNJY= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0/go.mod h1:hL9TGc07RkJVzDIBxsYXC/r0M+YiRkvl4z1elXCD+8s= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 h1:sgOdyT1ZAW3nErwCuvlGrkeP03pTtbRBW5MGCXWGZws= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 h1:f50d2lvCzW+yaZqWLzd1kU5808BeDBGdClUQybSzSVU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1/go.mod h1:fBbm1JLvufiabxBiiZWThNODf8+bARgZ81aP3CEx3sg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 h1:tBi9M7RlNXtG4USOpABQpCMbFpamTTGhN4JAHGdNGjc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0/go.mod h1:uFM6RUSMUQ7u9Hbtdmlg0D7kHqCKCpPxKELbb29rTdA= github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0 h1:cLpVMIkXC/umSP9DMz9I6FttDWJAsmvhpaB6MlkagGY= github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.1/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2 h1:d1hG+ChFZNyblEulXP3unkwzUmh83grtG3t4sMV+6Xg= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0 h1:5PmE4x8xzfL3onRdC5adQPrJSMDhYT2h5DwPB1uR9tA= github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0/go.mod h1:UL/d4lvWAzSJUuX+19uKdN0ktyjoOyQhgY+HWNgtIYI= diff --git a/sdk/arm/network/2020-03-01/armnetwork/go.mod b/sdk/arm/network/2020-03-01/armnetwork/go.mod index 864be2e3d5a3..32eddbd5918d 100644 --- a/sdk/arm/network/2020-03-01/armnetwork/go.mod +++ b/sdk/arm/network/2020-03-01/armnetwork/go.mod @@ -4,11 +4,9 @@ go 1.13 require ( github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.0.0-00010101000000-000000000000 + github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0 ) -replace github.com/Azure/azure-sdk-for-go/sdk/azidentity => ../../../../azidentity - replace github.com/Azure/azure-sdk-for-go/sdk/arm/resources/2019-05-01/armresources => ../../../resources/2019-05-01/armresources diff --git a/sdk/arm/network/2020-03-01/armnetwork/go.sum b/sdk/arm/network/2020-03-01/armnetwork/go.sum index 0d2a0bcb2b8e..9155ce0e045b 100644 --- a/sdk/arm/network/2020-03-01/armnetwork/go.sum +++ b/sdk/arm/network/2020-03-01/armnetwork/go.sum @@ -1,12 +1,15 @@ github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0 h1:i4/txgB7gpzLa3YBBPnSSXnRB5+oOd+79M3EhlaaEHM= github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0/go.mod h1:/cH2D+NpD2KRgnop4cU+S5P2On5mP6KWgpWq48+Bt/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0 h1:ogZVkNX3wS6ekWS3hD9sQCghWIGfw8CQ9JKv0rQQlVw= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0/go.mod h1:UKq2za3CMGx75vfPM9tPSuTBNODR4hX1qAeb+GRoDkc= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 h1:VdhfbVpQ3dkhXYOx/Wj1+utikcZkZSZSmpqmXWwaNJY= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0/go.mod h1:hL9TGc07RkJVzDIBxsYXC/r0M+YiRkvl4z1elXCD+8s= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 h1:sgOdyT1ZAW3nErwCuvlGrkeP03pTtbRBW5MGCXWGZws= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 h1:f50d2lvCzW+yaZqWLzd1kU5808BeDBGdClUQybSzSVU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1/go.mod h1:fBbm1JLvufiabxBiiZWThNODf8+bARgZ81aP3CEx3sg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 h1:tBi9M7RlNXtG4USOpABQpCMbFpamTTGhN4JAHGdNGjc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0/go.mod h1:uFM6RUSMUQ7u9Hbtdmlg0D7kHqCKCpPxKELbb29rTdA= github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0 h1:cLpVMIkXC/umSP9DMz9I6FttDWJAsmvhpaB6MlkagGY= github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.1/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2 h1:d1hG+ChFZNyblEulXP3unkwzUmh83grtG3t4sMV+6Xg= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0 h1:5PmE4x8xzfL3onRdC5adQPrJSMDhYT2h5DwPB1uR9tA= github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0/go.mod h1:UL/d4lvWAzSJUuX+19uKdN0ktyjoOyQhgY+HWNgtIYI= diff --git a/sdk/arm/resources/2019-05-01/armresources/go.mod b/sdk/arm/resources/2019-05-01/armresources/go.mod index b06ae670d95a..2acdc72f09bf 100644 --- a/sdk/arm/resources/2019-05-01/armresources/go.mod +++ b/sdk/arm/resources/2019-05-01/armresources/go.mod @@ -4,9 +4,7 @@ go 1.13 require ( github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.0.0-00010101000000-000000000000 + github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0 ) - -replace github.com/Azure/azure-sdk-for-go/sdk/azidentity => ../../../../azidentity diff --git a/sdk/arm/resources/2019-05-01/armresources/go.sum b/sdk/arm/resources/2019-05-01/armresources/go.sum index 0d2a0bcb2b8e..9155ce0e045b 100644 --- a/sdk/arm/resources/2019-05-01/armresources/go.sum +++ b/sdk/arm/resources/2019-05-01/armresources/go.sum @@ -1,12 +1,15 @@ github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0 h1:i4/txgB7gpzLa3YBBPnSSXnRB5+oOd+79M3EhlaaEHM= github.com/Azure/azure-sdk-for-go/sdk/armcore v0.1.0/go.mod h1:/cH2D+NpD2KRgnop4cU+S5P2On5mP6KWgpWq48+Bt/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0 h1:ogZVkNX3wS6ekWS3hD9sQCghWIGfw8CQ9JKv0rQQlVw= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0/go.mod h1:UKq2za3CMGx75vfPM9tPSuTBNODR4hX1qAeb+GRoDkc= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 h1:VdhfbVpQ3dkhXYOx/Wj1+utikcZkZSZSmpqmXWwaNJY= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0/go.mod h1:hL9TGc07RkJVzDIBxsYXC/r0M+YiRkvl4z1elXCD+8s= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 h1:sgOdyT1ZAW3nErwCuvlGrkeP03pTtbRBW5MGCXWGZws= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 h1:f50d2lvCzW+yaZqWLzd1kU5808BeDBGdClUQybSzSVU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1/go.mod h1:fBbm1JLvufiabxBiiZWThNODf8+bARgZ81aP3CEx3sg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 h1:tBi9M7RlNXtG4USOpABQpCMbFpamTTGhN4JAHGdNGjc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0/go.mod h1:uFM6RUSMUQ7u9Hbtdmlg0D7kHqCKCpPxKELbb29rTdA= github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0 h1:cLpVMIkXC/umSP9DMz9I6FttDWJAsmvhpaB6MlkagGY= github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.1/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2 h1:d1hG+ChFZNyblEulXP3unkwzUmh83grtG3t4sMV+6Xg= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0 h1:5PmE4x8xzfL3onRdC5adQPrJSMDhYT2h5DwPB1uR9tA= github.com/Azure/azure-sdk-for-go/sdk/to v0.1.0/go.mod h1:UL/d4lvWAzSJUuX+19uKdN0ktyjoOyQhgY+HWNgtIYI= diff --git a/sdk/azidentity/aad_identity_client.go b/sdk/azidentity/aad_identity_client.go deleted file mode 100644 index 3b4dc4c917ab..000000000000 --- a/sdk/azidentity/aad_identity_client.go +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "bufio" - "context" - "crypto/rsa" - "crypto/x509" - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "net/http" - "net/url" - "os" - "path" - "strings" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - clientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" - tokenEndpoint = "/oauth2/v2.0/token/" -) - -const ( - qpClientAssertionType = "client_assertion_type" - qpClientAssertion = "client_assertion" - qpClientID = "client_id" - qpClientSecret = "client_secret" - qpDeviceCode = "device_code" - qpGrantType = "grant_type" - qpPassword = "password" - qpRefreshToken = "refresh_token" - qpResponseType = "response_type" - qpScope = "scope" - qpUsername = "username" -) - -// aadIdentityClient provides the base for authenticating with Client Secret Credentials, Client Certificate Credentials -// and Environment Credentials. This type inlcudes an azcore.Pipeline and TokenCredentialOptions. -type aadIdentityClient struct { - options TokenCredentialOptions - pipeline azcore.Pipeline -} - -// newAADIdentityClient creates a new instance of the aadIdentityClient with the TokenCredentialOptions -// that are passed into it along with a default pipeline. -// options: TokenCredentialOptions that can configure policies for the pipeline and the authority host that -// will be used to retrieve tokens and authenticate -func newAADIdentityClient(options *TokenCredentialOptions) (*aadIdentityClient, error) { - logEnvVars() - options, err := options.setDefaultValues() - if err != nil { - return nil, err - } - return &aadIdentityClient{options: *options, pipeline: newDefaultPipeline(*options)}, nil -} - -// refreshAccessToken creates a refresh token request and returns the resulting Access Token or -// an error in case of an authentication failure. -// ctx: The current request context -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal -// clientID: The client (application) ID of the service principal -// clientSecret: A client secret that was generated for the App Registration used to authenticate the client -// scopes: The scopes for the given access token -func (c *aadIdentityClient) refreshAccessToken(ctx context.Context, tenantID string, clientID string, clientSecret string, refreshToken string, scopes []string) (*tokenResponse, error) { - msg, err := c.createRefreshTokenRequest(tenantID, clientID, clientSecret, refreshToken, scopes) - if err != nil { - return nil, err - } - - resp, err := c.pipeline.Do(ctx, msg) - if err != nil { - return nil, err - } - - if resp.HasStatusCode(successStatusCodes[:]...) { - return c.createRefreshAccessToken(resp) - } - - return nil, &AuthenticationFailedError{inner: newAADAuthenticationFailedError(resp)} -} - -// authenticate creates a client secret authentication request and returns the resulting Access Token or -// an error in case of authentication failure. -// ctx: The current request context -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal -// clientID: The client (application) ID of the service principal -// clientSecret: A client secret that was generated for the App Registration used to authenticate the client -// scopes: The scopes required for the token -func (c *aadIdentityClient) authenticate(ctx context.Context, tenantID string, clientID string, clientSecret string, scopes []string) (*azcore.AccessToken, error) { - msg, err := c.createClientSecretAuthRequest(tenantID, clientID, clientSecret, scopes) - if err != nil { - return nil, err - } - - resp, err := c.pipeline.Do(ctx, msg) - if err != nil { - return nil, err - } - - if resp.HasStatusCode(successStatusCodes[:]...) { - return c.createAccessToken(resp) - } - - return nil, &AuthenticationFailedError{inner: newAADAuthenticationFailedError(resp)} -} - -// authenticateCertificate creates a client certificate authentication request and returns an Access Token or -// an error. -// ctx: The current request context -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal -// clientID: The client (application) ID of the service principal -// clientCertificatePath: The path to the client certificate PEM file -// scopes: The scopes required for the token -func (c *aadIdentityClient) authenticateCertificate(ctx context.Context, tenantID string, clientID string, clientCertificatePath string, scopes []string) (*azcore.AccessToken, error) { - msg, err := c.createClientCertificateAuthRequest(tenantID, clientID, clientCertificatePath, scopes) - if err != nil { - return nil, err - } - - resp, err := c.pipeline.Do(ctx, msg) - if err != nil { - return nil, err - } - - if resp.HasStatusCode(successStatusCodes[:]...) { - return c.createAccessToken(resp) - } - - return nil, &AuthenticationFailedError{inner: newAADAuthenticationFailedError(resp)} -} - -func (c *aadIdentityClient) createAccessToken(res *azcore.Response) (*azcore.AccessToken, error) { - value := struct { // TODO comment - Token string `json:"access_token"` - ExpiresIn json.Number `json:"expires_in"` - ExpiresOn string `json:"expires_on"` - }{} - if err := res.UnmarshalAsJSON(&value); err != nil { - return nil, fmt.Errorf("internal AccessToken: %w", err) - } - t, err := value.ExpiresIn.Int64() - if err != nil { - return nil, err - } - return &azcore.AccessToken{ - Token: value.Token, - ExpiresOn: time.Now().Add(time.Second * time.Duration(t)).UTC(), - }, nil -} - -func (c *aadIdentityClient) createRefreshAccessToken(res *azcore.Response) (*tokenResponse, error) { - // To know more about refreshing access tokens please see: https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code#refreshing-the-access-tokens - // DeviceCodeCredential uses refresh token, please see the authentication flow here: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code - value := struct { - Token string `json:"access_token"` - RefreshToken string `json:"refresh_token"` - ExpiresIn json.Number `json:"expires_in"` - ExpiresOn string `json:"expires_on"` - }{} - if err := res.UnmarshalAsJSON(&value); err != nil { - return nil, fmt.Errorf("internal AccessToken: %w", err) - } - t, err := value.ExpiresIn.Int64() - if err != nil { - return nil, err - } - accessToken := &azcore.AccessToken{ - Token: value.Token, - ExpiresOn: time.Now().Add(time.Second * time.Duration(t)).UTC(), - } - return &tokenResponse{token: accessToken, refreshToken: value.RefreshToken}, nil -} - -func (c *aadIdentityClient) createRefreshTokenRequest(tenantID, clientID, clientSecret, refreshToken string, scopes []string) (*azcore.Request, error) { - u := *c.options.AuthorityHost - u.Path = path.Join(u.Path, tenantID, tokenEndpoint) - data := url.Values{} - data.Set(qpGrantType, "refresh_token") - data.Set(qpClientID, clientID) - // clientSecret is only required for web apps. To know more about refreshing access tokens please see: https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code#refreshing-the-access-tokens - if len(clientSecret) != 0 { - data.Set(qpClientSecret, clientSecret) - } - data.Set(qpRefreshToken, refreshToken) - data.Set(qpScope, strings.Join(scopes, " ")) - dataEncoded := data.Encode() - body := azcore.NopCloser(strings.NewReader(dataEncoded)) - req := azcore.NewRequest(http.MethodPost, u) - req.Header.Set(azcore.HeaderContentType, azcore.HeaderURLEncoded) - err := req.SetBody(body) - if err != nil { - return nil, err - } - return req, nil -} - -func (c *aadIdentityClient) createClientSecretAuthRequest(tenantID string, clientID string, clientSecret string, scopes []string) (*azcore.Request, error) { - u := *c.options.AuthorityHost - u.Path = path.Join(u.Path, tenantID, tokenEndpoint) - data := url.Values{} - data.Set(qpGrantType, "client_credentials") - data.Set(qpClientID, clientID) - data.Set(qpClientSecret, clientSecret) - data.Set(qpScope, strings.Join(scopes, " ")) - dataEncoded := data.Encode() - body := azcore.NopCloser(strings.NewReader(dataEncoded)) - req := azcore.NewRequest(http.MethodPost, u) - req.Header.Set(azcore.HeaderContentType, azcore.HeaderURLEncoded) - err := req.SetBody(body) - if err != nil { - return nil, err - } - - return req, nil -} - -func (c *aadIdentityClient) createClientCertificateAuthRequest(tenantID string, clientID string, clientCertificate string, scopes []string) (*azcore.Request, error) { - u := *c.options.AuthorityHost - u.Path = path.Join(u.Path, tenantID, tokenEndpoint) - clientAssertion, err := createClientAssertionJWT(clientID, u.String(), clientCertificate) - if err != nil { - return nil, err - } - data := url.Values{} - data.Set(qpGrantType, "client_credentials") - data.Set(qpResponseType, "token") - data.Set(qpClientID, clientID) - data.Set(qpClientAssertionType, clientAssertionType) - data.Set(qpClientAssertion, clientAssertion) - data.Set(qpScope, strings.Join(scopes, " ")) - dataEncoded := data.Encode() - body := azcore.NopCloser(strings.NewReader(dataEncoded)) - req := azcore.NewRequest(http.MethodPost, u) - req.Header.Set(azcore.HeaderContentType, azcore.HeaderURLEncoded) - err = req.SetBody(body) - if err != nil { - return nil, err - } - return req, nil -} - -// authenticateUsernamePassword creates a client username and password authentication request and returns an Access Token or -// an error. -// ctx: The current request context -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal -// clientID: The client (application) ID of the service principal -// username: User's account username -// password: User's account password -// scopes: The scopes required for the token -func (c *aadIdentityClient) authenticateUsernamePassword(ctx context.Context, tenantID string, clientID string, username string, password string, scopes []string) (*azcore.AccessToken, error) { - msg, err := c.createUsernamePasswordAuthRequest(tenantID, clientID, username, password, scopes) - if err != nil { - return nil, err - } - - resp, err := c.pipeline.Do(ctx, msg) - if err != nil { - return nil, err - } - - if resp.HasStatusCode(successStatusCodes[:]...) { - return c.createAccessToken(resp) - } - - return nil, &AuthenticationFailedError{inner: newAADAuthenticationFailedError(resp)} -} - -func (c *aadIdentityClient) createUsernamePasswordAuthRequest(tenantID string, clientID string, username string, password string, scopes []string) (*azcore.Request, error) { - u := *c.options.AuthorityHost - u.Path = path.Join(u.Path, tenantID, tokenEndpoint) - data := url.Values{} - data.Set(qpResponseType, "token") - data.Set(qpGrantType, "password") - data.Set(qpClientID, clientID) - data.Set(qpUsername, username) - data.Set(qpPassword, password) - data.Set(qpScope, strings.Join(scopes, " ")) - dataEncoded := data.Encode() - body := azcore.NopCloser(strings.NewReader(dataEncoded)) - req := azcore.NewRequest(http.MethodPost, u) - req.Header.Set(azcore.HeaderContentType, azcore.HeaderURLEncoded) - err := req.SetBody(body) - if err != nil { - return nil, err - } - return req, nil -} - -func createDeviceCodeResult(res *azcore.Response) (*deviceCodeResult, error) { - value := &deviceCodeResult{} - if err := res.UnmarshalAsJSON(&value); err != nil { - return nil, fmt.Errorf("DeviceCodeResult: %w", err) - } - return value, nil -} - -// authenticateDeviceCode creates a device code authentication request and returns an Access Token or -// an error in case of failure. -// ctx: The current request context -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal -// clientID: The client (application) ID of the service principal -// deviceCode: The device code associated with the request -// scopes: The scopes required for the token -func (c *aadIdentityClient) authenticateDeviceCode(ctx context.Context, tenantID string, clientID string, deviceCode string, scopes []string) (*tokenResponse, error) { - msg, err := c.createDeviceCodeAuthRequest(tenantID, clientID, deviceCode, scopes) - if err != nil { - return nil, err - } - - resp, err := c.pipeline.Do(ctx, msg) - if err != nil { - return nil, err - } - - if resp.HasStatusCode(successStatusCodes[:]...) { - return c.createRefreshAccessToken(resp) - } - - return nil, &AuthenticationFailedError{inner: newAADAuthenticationFailedError(resp)} -} - -func (c *aadIdentityClient) createDeviceCodeAuthRequest(tenantID string, clientID string, deviceCode string, scopes []string) (*azcore.Request, error) { - if len(tenantID) == 0 { // if the user did not pass in a tenantID then the default value is set - tenantID = "organizations" - } - u := *c.options.AuthorityHost - u.Path = path.Join(u.Path, tenantID, tokenEndpoint) - data := url.Values{} - data.Set(qpGrantType, deviceCodeGrantType) - data.Set(qpClientID, clientID) - data.Set(qpDeviceCode, deviceCode) - data.Set(qpScope, strings.Join(scopes, " ")) - dataEncoded := data.Encode() - body := azcore.NopCloser(strings.NewReader(dataEncoded)) - req := azcore.NewRequest(http.MethodPost, u) - req.Header.Set(azcore.HeaderContentType, azcore.HeaderURLEncoded) - err := req.SetBody(body) - if err != nil { - return nil, err - } - return req, nil -} - -func (c *aadIdentityClient) requestNewDeviceCode(ctx context.Context, tenantID, clientID string, scopes []string) (*deviceCodeResult, error) { - msg, err := c.createDeviceCodeNumberRequest(tenantID, clientID, scopes) - if err != nil { - return nil, err - } - - resp, err := c.pipeline.Do(ctx, msg) - if err != nil { - return nil, err - } - - if resp.HasStatusCode(successStatusCodes[:]...) { - return createDeviceCodeResult(resp) - } - return nil, &AuthenticationFailedError{inner: newAADAuthenticationFailedError(resp)} -} - -func (c *aadIdentityClient) createDeviceCodeNumberRequest(tenantID string, clientID string, scopes []string) (*azcore.Request, error) { - if len(tenantID) == 0 { // if the user did not pass in a tenantID then the default value is set - tenantID = "organizations" - } - u := *c.options.AuthorityHost - u.Path = path.Join(u.Path, tenantID, "/oauth2/v2.0/devicecode") // endpoint that will return a device code along with the other necessary authentication flow parameters in the DeviceCodeResult struct - data := url.Values{} - data.Set(qpClientID, clientID) - data.Set(qpScope, strings.Join(scopes, " ")) - dataEncoded := data.Encode() - body := azcore.NopCloser(strings.NewReader(dataEncoded)) - req := azcore.NewRequest(http.MethodPost, u) - req.Header.Set(azcore.HeaderContentType, azcore.HeaderURLEncoded) - err := req.SetBody(body) - if err != nil { - return nil, err - } - return req, nil -} - -func getPrivateKey(cert string) (*rsa.PrivateKey, error) { - privateKeyFile, err := os.Open(cert) - if err != nil { - return nil, fmt.Errorf("Opening certificate file path: %w", err) - } - defer privateKeyFile.Close() - - pemFileInfo, err := privateKeyFile.Stat() - if err != nil { - return nil, fmt.Errorf("Getting certificate file info: %w", err) - } - size := pemFileInfo.Size() - - pemBytes := make([]byte, size) - buffer := bufio.NewReader(privateKeyFile) - _, err = buffer.Read(pemBytes) - if err != nil { - return nil, fmt.Errorf("Read PEM file bytes: %w", err) - } - - data, rest := pem.Decode([]byte(pemBytes)) - const privateKeyBlock = "PRIVATE KEY" - // NOTE: check types of private keys - if data.Type != privateKeyBlock { - for len(rest) > 0 { - data, rest = pem.Decode(rest) - if data.Type == privateKeyBlock { - privateKeyImported, err := x509.ParsePKCS8PrivateKey(data.Bytes) - if err != nil { - return nil, fmt.Errorf("ParsePKCS8PrivateKey: %w", err) - } - - return privateKeyImported.(*rsa.PrivateKey), nil - } - } - return nil, errors.New("Cannot find PRIVATE KEY in file") - } - // NOTE: this could be a function local closure - privateKeyImported, err := x509.ParsePKCS8PrivateKey(data.Bytes) - if err != nil { - return nil, fmt.Errorf("ParsePKCS8PrivateKey: %w", err) - } - - return privateKeyImported.(*rsa.PrivateKey), nil -} diff --git a/sdk/azidentity/aad_identity_client_test.go b/sdk/azidentity/aad_identity_client_test.go deleted file mode 100644 index 92d942b28237..000000000000 --- a/sdk/azidentity/aad_identity_client_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "net/url" - "testing" -) - -func TestAzurePublicCloudParse(t *testing.T) { - _, err := url.Parse(AzurePublicCloud) - if err != nil { - t.Fatalf("Failed to parse default authority host: %v", err) - } -} - -func TestAzureChinaParse(t *testing.T) { - _, err := url.Parse(AzureChina) - if err != nil { - t.Fatalf("Failed to parse AzureChina authority host: %v", err) - } -} - -func TestAzureGermanyParse(t *testing.T) { - _, err := url.Parse(AzureGermany) - if err != nil { - t.Fatalf("Failed to parse AzureGermany authority host: %v", err) - } -} - -func TestAzureGovernmentParse(t *testing.T) { - _, err := url.Parse(AzureGovernment) - if err != nil { - t.Fatalf("Failed to parse AzureGovernment authority host: %v", err) - } -} diff --git a/sdk/azidentity/azidentity.go b/sdk/azidentity/azidentity.go deleted file mode 100644 index fbcae97f81e5..000000000000 --- a/sdk/azidentity/azidentity.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "net/http" - "net/url" - "os" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - // AzureChina is a global constant to use in order to access the Azure China cloud. - AzureChina = "https://login.chinacloudapi.cn/" - // AzureGermany is a global constant to use in order to access the Azure Germany cloud. - AzureGermany = "https://login.microsoftonline.de/" - // AzureGovernment is a global constant to use in order to access the Azure Government cloud. - AzureGovernment = "https://login.microsoftonline.us/" - // AzurePublicCloud is a global constant to use in order to access the Azure public cloud. - AzurePublicCloud = "https://login.microsoftonline.com/" - // defaultSuffix is a suffix the signals that a string is in scope format - defaultSuffix = "/.default" -) - -var ( - successStatusCodes = [2]int{ - http.StatusOK, // 200 - http.StatusCreated, // 201 - } -) - -type tokenResponse struct { - token *azcore.AccessToken - refreshToken string -} - -// AADAuthenticationFailedError is used to unmarshal error responses received from Azure Active Directory. -type AADAuthenticationFailedError struct { - Message string `json:"error"` - Description string `json:"error_description"` - Timestamp string `json:"timestamp"` - TraceID string `json:"trace_id"` - CorrelationID string `json:"correlation_id"` - URI string `json:"error_uri"` - Response *azcore.Response -} - -func (e *AADAuthenticationFailedError) Error() string { - msg := e.Message - if len(e.Description) > 0 { - msg += " " + e.Description - } - return msg -} - -// AuthenticationFailedError is returned when the authentication request has failed. -type AuthenticationFailedError struct { - inner error - msg string -} - -// Unwrap method on AuthenticationFailedError provides access to the inner error if available. -func (e *AuthenticationFailedError) Unwrap() error { - return e.inner -} - -// IsNotRetriable returns true indicating that this is a terminal error. -func (e *AuthenticationFailedError) IsNotRetriable() bool { - return true -} - -func (e *AuthenticationFailedError) Error() string { - if len(e.msg) == 0 { - e.msg = e.inner.Error() - } - return e.msg -} - -func newAADAuthenticationFailedError(resp *azcore.Response) error { - authFailed := &AADAuthenticationFailedError{Response: resp} - err := resp.UnmarshalAsJSON(authFailed) - if err != nil { - authFailed.Message = resp.Status - authFailed.Description = "Failed to unmarshal response: " + err.Error() - } - return authFailed -} - -// CredentialUnavailableError is the error type returned when the conditions required to -// create a credential do not exist or are unavailable. -type CredentialUnavailableError struct { - // CredentialType holds the name of the credential that is unavailable - CredentialType string - // Message contains the reason why the credential is unavailable - Message string -} - -func (e *CredentialUnavailableError) Error() string { - return e.CredentialType + ": " + e.Message -} - -// IsNotRetriable returns true indicating that this is a terminal error. -func (e *CredentialUnavailableError) IsNotRetriable() bool { - return true -} - -// TokenCredentialOptions are used to configure how requests are made to Azure Active Directory. -type TokenCredentialOptions struct { - // The host of the Azure Active Directory authority. The default is https://login.microsoft.com - AuthorityHost *url.URL - - // HTTPClient sets the transport for making HTTP requests - // Leave this as nil to use the default HTTP transport - HTTPClient azcore.Transport - - // LogOptions configures the built-in request logging policy behavior - LogOptions azcore.RequestLogOptions - - // Retry configures the built-in retry policy behavior - Retry *azcore.RetryOptions - - // Telemetry configures the built-in telemetry policy behavior - Telemetry azcore.TelemetryOptions -} - -// setDefaultValues initializes an instance of TokenCredentialOptions with default settings. -func (c *TokenCredentialOptions) setDefaultValues() (*TokenCredentialOptions, error) { - authorityHost := AzurePublicCloud - if envAuthorityHost := os.Getenv("AZURE_AUTHORITY_HOST"); envAuthorityHost != "" { - authorityHost = envAuthorityHost - } - - if c == nil { - defaultAuthorityHostURL, err := url.Parse(authorityHost) - if err != nil { - return nil, err - } - c = &TokenCredentialOptions{AuthorityHost: defaultAuthorityHostURL} - } - - if c.AuthorityHost == nil { - defaultAuthorityHostURL, err := url.Parse(authorityHost) - if err != nil { - return nil, err - } - c.AuthorityHost = defaultAuthorityHostURL - } - - if len(c.AuthorityHost.Path) == 0 || c.AuthorityHost.Path[len(c.AuthorityHost.Path)-1:] != "/" { - c.AuthorityHost.Path = c.AuthorityHost.Path + "/" - } - - return c, nil -} - -// newDefaultPipeline creates a pipeline using the specified pipeline options. -func newDefaultPipeline(o TokenCredentialOptions) azcore.Pipeline { - if o.HTTPClient == nil { - o.HTTPClient = azcore.DefaultHTTPClientTransport() - } - - return azcore.NewPipeline( - o.HTTPClient, - azcore.NewTelemetryPolicy(o.Telemetry), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(o.Retry), - azcore.NewRequestLogPolicy(o.LogOptions)) -} - -// newDefaultMSIPipeline creates a pipeline using the specified pipeline options needed -// for a Managed Identity, such as a MSI specific retry policy. -func newDefaultMSIPipeline(o ManagedIdentityCredentialOptions) azcore.Pipeline { - if o.HTTPClient == nil { - o.HTTPClient = azcore.DefaultHTTPClientTransport() - } - var statusCodes []int - // retry policy for MSI is not end-user configurable - retryOpts := azcore.RetryOptions{ - MaxRetries: 4, - RetryDelay: 2 * time.Second, - TryTimeout: 1 * time.Minute, - StatusCodes: append(statusCodes, - // The following status codes are a subset of those found in azcore.StatusCodesForRetry, these are the only ones specifically needed for MSI scenarios - http.StatusRequestTimeout, // 408 - http.StatusTooManyRequests, // 429 - http.StatusInternalServerError, // 500 - http.StatusBadGateway, // 502 - http.StatusGatewayTimeout, // 504 - http.StatusNotFound, - http.StatusGone, - // all remaining 5xx - http.StatusNotImplemented, - http.StatusHTTPVersionNotSupported, - http.StatusVariantAlsoNegotiates, - http.StatusInsufficientStorage, - http.StatusLoopDetected, - http.StatusNotExtended, - http.StatusNetworkAuthenticationRequired), - } - - return azcore.NewPipeline( - o.HTTPClient, - azcore.NewTelemetryPolicy(o.Telemetry), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(&retryOpts), - azcore.NewRequestLogPolicy(o.LogOptions)) -} diff --git a/sdk/azidentity/azidentity_test.go b/sdk/azidentity/azidentity_test.go deleted file mode 100644 index 433203750481..000000000000 --- a/sdk/azidentity/azidentity_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "net/url" - "os" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - envHostString = "https://mock.com/" - customHostString = "https://custommock.com/" -) - -func Test_AuthorityHost_Parse(t *testing.T) { - _, err := url.Parse(AzurePublicCloud) - if err != nil { - t.Fatalf("Failed to parse default authority host: %v", err) - } -} - -func Test_NonNilTokenCredentialOptsNilAuthorityHost(t *testing.T) { - opts := &TokenCredentialOptions{Retry: &azcore.RetryOptions{MaxRetries: 6}} - opts, err := opts.setDefaultValues() - if err != nil { - t.Fatalf("Received an error: %v", err) - } - if opts.AuthorityHost == nil { - t.Fatalf("Did not set default authority host") - } -} - -func Test_SetEnvAuthorityHost(t *testing.T) { - err := os.Setenv("AZURE_AUTHORITY_HOST", envHostString) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - - opts := &TokenCredentialOptions{} - opts, err = opts.setDefaultValues() - if opts.AuthorityHost.String() != envHostString { - t.Fatalf("Unexpected error when get host from environment vairable: %v", err) - } - - // Unset that host environment vairable to avoid other tests failed. - err = os.Unsetenv("AZURE_AUTHORITY_HOST") - if err != nil { - t.Fatalf("Unexpected error when unset environment vairable: %v", err) - } -} - -func Test_CustomAuthorityHost(t *testing.T) { - err := os.Setenv("AZURE_AUTHORITY_HOST", envHostString) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - - customHost, err := url.Parse(customHostString) - if err != nil { - t.Fatalf("Received an error: %v", err) - } - - opts := &TokenCredentialOptions{AuthorityHost: customHost} - opts, err = opts.setDefaultValues() - if opts.AuthorityHost.String() != customHostString { - t.Fatalf("Unexpected error when get host from environment vairable: %v", err) - } - - // Unset that host environment vairable to avoid other tests failed. - err = os.Unsetenv("AZURE_AUTHORITY_HOST") - if err != nil { - t.Fatalf("Unexpected error when unset environment vairable: %v", err) - } -} - -func Test_DefaultAuthorityHost(t *testing.T) { - opts := &TokenCredentialOptions{} - opts, err := opts.setDefaultValues() - if opts.AuthorityHost.String() != AzurePublicCloud { - t.Fatalf("Unexpected error when set default AuthorityHost: %v", err) - } -} - -func Test_AzureGermanyAuthorityHost(t *testing.T) { - opts := &TokenCredentialOptions{} - opts, err := opts.setDefaultValues() - if err != nil { - t.Fatal(err) - } - u, err := url.Parse(AzureGermany) - if err != nil { - t.Fatal(err) - } - opts.AuthorityHost = u - if opts.AuthorityHost.String() != AzureGermany { - t.Fatalf("Did not retrieve expected authority host string") - } -} - -func Test_AzureChinaAuthorityHost(t *testing.T) { - opts := &TokenCredentialOptions{} - opts, err := opts.setDefaultValues() - if err != nil { - t.Fatal(err) - } - u, err := url.Parse(AzureChina) - if err != nil { - t.Fatal(err) - } - opts.AuthorityHost = u - if opts.AuthorityHost.String() != AzureChina { - t.Fatalf("Did not retrieve expected authority host string") - } -} - -func Test_AzureGovernmentAuthorityHost(t *testing.T) { - opts := &TokenCredentialOptions{} - opts, err := opts.setDefaultValues() - if err != nil { - t.Fatal(err) - } - u, err := url.Parse(AzureGovernment) - if err != nil { - t.Fatal(err) - } - opts.AuthorityHost = u - if opts.AuthorityHost.String() != AzureGovernment { - t.Fatalf("Did not retrieve expected authority host string") - } -} diff --git a/sdk/azidentity/azure_cli_credential.go b/sdk/azidentity/azure_cli_credential.go deleted file mode 100644 index 220109ab5453..000000000000 --- a/sdk/azidentity/azure_cli_credential.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "os" - "os/exec" - "regexp" - "runtime" - "strings" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// AzureCLITokenProvider can be used to supply the AzureCLICredential with an alternate token provider -type AzureCLITokenProvider func(ctx context.Context, resource string) ([]byte, error) - -// AzureCLICredentialOptions contains options used to configure the AzureCLICredential -type AzureCLICredentialOptions struct { - TokenProvider AzureCLITokenProvider -} - -// AzureCLICredential enables authentication to Azure Active Directory using the Azure CLI command "az account get-access-token". -type AzureCLICredential struct { - tokenProvider AzureCLITokenProvider -} - -// NewAzureCLICredential constructs a new AzureCLICredential with the details needed to authenticate against Azure Active Directory -// options: configure the management of the requests sent to Azure Active Directory. -func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredential, error) { - if options == nil { - options = &AzureCLICredentialOptions{TokenProvider: defaultTokenProvider()} - } - return &AzureCLICredential{ - tokenProvider: options.TokenProvider, - }, nil -} - -// GetToken obtains a token from Azure Active Directory, using the Azure CLI command to authenticate. -// ctx: Context used to control the request lifetime. -// opts: TokenRequestOptions contains the list of scopes for which the token will have access. -// Returns an AccessToken which can be used to authenticate service client calls. -func (c *AzureCLICredential) GetToken(ctx context.Context, opts azcore.TokenRequestOptions) (*azcore.AccessToken, error) { - // The following code will remove the /.default suffix from the scope passed into the method since AzureCLI expect a resource string instead of a scope string - opts.Scopes[0] = strings.TrimSuffix(opts.Scopes[0], defaultSuffix) - at, err := c.authenticate(ctx, opts.Scopes[0]) - if err != nil { - addGetTokenFailureLogs("Azure CLI Credential", err) - return nil, err - } - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - return at, nil -} - -// AuthenticationPolicy implements the azcore.Credential interface on AzureCLICredential and calls the Bearer Token policy -// to get the bearer token. -func (c *AzureCLICredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) -} - -const timeoutCLIRequest = 10000 * time.Millisecond - -// authenticate creates a client secret authentication request and returns the resulting Access Token or -// an error in case of authentication failure. -// ctx: The current request context -// scopes: The scopes for which the token has access -func (c *AzureCLICredential) authenticate(ctx context.Context, resource string) (*azcore.AccessToken, error) { - output, err := c.tokenProvider(ctx, resource) - if err != nil { - return nil, err - } - - return c.createAccessToken(output) -} - -func defaultTokenProvider() func(ctx context.Context, resource string) ([]byte, error) { - return func(ctx context.Context, resource string) ([]byte, error) { - // This is the path that a developer can set to tell this class what the install path for Azure CLI is. - const azureCLIPath = "AZURE_CLI_PATH" - - // The default install paths are used to find Azure CLI. This is for security, so that any path in the calling program's Path environment is not used to execute Azure CLI. - azureCLIDefaultPathWindows := fmt.Sprintf("%s\\Microsoft SDKs\\Azure\\CLI2\\wbin; %s\\Microsoft SDKs\\Azure\\CLI2\\wbin", os.Getenv("ProgramFiles(x86)"), os.Getenv("ProgramFiles")) - - // Default path for non-Windows. - const azureCLIDefaultPath = "/bin:/sbin:/usr/bin:/usr/local/bin" - - // Validate resource, since it gets sent as a command line argument to Azure CLI - const invalidResourceErrorTemplate = "Resource %s is not in expected format. Only alphanumeric characters, [dot], [colon], [hyphen], and [forward slash] are allowed." - match, err := regexp.MatchString("^[0-9a-zA-Z-.:/]+$", resource) - if err != nil { - return nil, err - } - if !match { - return nil, fmt.Errorf(invalidResourceErrorTemplate, resource) - } - - ctx, cancel := context.WithTimeout(ctx, timeoutCLIRequest) - defer cancel() - - // Execute Azure CLI to get token - var cliCmd *exec.Cmd - if runtime.GOOS == "windows" { - cliCmd = exec.CommandContext(ctx, fmt.Sprintf("%s\\system32\\cmd.exe", os.Getenv("windir"))) - cliCmd.Env = os.Environ() - cliCmd.Env = append(cliCmd.Env, fmt.Sprintf("PATH=%s;%s", os.Getenv(azureCLIPath), azureCLIDefaultPathWindows)) - cliCmd.Args = append(cliCmd.Args, "/c", "az") - } else { - cliCmd = exec.CommandContext(ctx, "az") - cliCmd.Env = os.Environ() - cliCmd.Env = append(cliCmd.Env, fmt.Sprintf("PATH=%s:%s", os.Getenv(azureCLIPath), azureCLIDefaultPath)) - } - cliCmd.Args = append(cliCmd.Args, "account", "get-access-token", "-o", "json", "--resource", resource) - - var stderr bytes.Buffer - cliCmd.Stderr = &stderr - - output, err := cliCmd.Output() - if err != nil { - return nil, &CredentialUnavailableError{CredentialType: "Azure CLI Credential", Message: stderr.String()} - } - - return output, nil - } -} - -func (c *AzureCLICredential) createAccessToken(tk []byte) (*azcore.AccessToken, error) { - t := struct { - AccessToken string `json:"accessToken"` - Authority string `json:"_authority"` - ClientID string `json:"_clientId"` - ExpiresOn string `json:"expiresOn"` - IdentityProvider string `json:"identityProvider"` - IsMRRT bool `json:"isMRRT"` - RefreshToken string `json:"refreshToken"` - Resource string `json:"resource"` - TokenType string `json:"tokenType"` - UserID string `json:"userId"` - }{} - err := json.Unmarshal(tk, &t) - if err != nil { - return nil, err - } - - tokenExpirationDate, err := parseExpirationDate(t.ExpiresOn) - if err != nil { - return nil, fmt.Errorf("Error parsing Token Expiration Date %q: %+v", t.ExpiresOn, err) - } - - converted := &azcore.AccessToken{ - Token: t.AccessToken, - ExpiresOn: *tokenExpirationDate, - } - return converted, nil -} - -// parseExpirationDate parses either a Azure CLI or CloudShell date into a time object -func parseExpirationDate(input string) (*time.Time, error) { - // CloudShell (and potentially the Azure CLI in future) - expirationDate, cloudShellErr := time.Parse(time.RFC3339, input) - if cloudShellErr != nil { - // Azure CLI (Python) e.g. 2017-08-31 19:48:57.998857 (plus the local timezone) - const cliFormat = "2006-01-02 15:04:05.999999" - expirationDate, cliErr := time.ParseInLocation(cliFormat, input, time.Local) - if cliErr != nil { - return nil, fmt.Errorf("Error parsing expiration date %q.\n\nCloudShell Error: \n%+v\n\nCLI Error:\n%+v", input, cloudShellErr, cliErr) - } - return &expirationDate, nil - } - return &expirationDate, nil -} diff --git a/sdk/azidentity/azure_cli_credential_test.go b/sdk/azidentity/azure_cli_credential_test.go deleted file mode 100644 index 3384371bb134..000000000000 --- a/sdk/azidentity/azure_cli_credential_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "fmt" - "net/http" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -var ( - mockCLITokenProviderSuccess = func(ctx context.Context, resource string) ([]byte, error) { - return []byte(" {\"accessToken\":\"mocktoken\" , " + - "\"expiresOn\": \"2007-01-01 01:01:01.079627\"," + - "\"subscription\": \"mocksub\"," + - "\"tenant\": \"mocktenant\"," + - "\"tokenType\": \"mocktype\"}"), nil - } - mockCLITokenProviderFailure = func(ctx context.Context, resource string) ([]byte, error) { - return nil, errors.New("provider failure message") - } -) - -func TestAzureCLICredential_GetTokenSuccess(t *testing.T) { - cred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TokenProvider: mockCLITokenProviderSuccess}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - at, err := cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - fmt.Println(err.Error()) - t.Fatalf("Expected an empty error but received: %v", err) - } - if len(at.Token) == 0 { - t.Fatalf(("Did not receive a token")) - } - if at.Token != "mocktoken" { - t.Fatalf(("Did not receive the correct access token")) - } -} - -func TestAzureCLICredential_GetTokenInvalidToken(t *testing.T) { - cred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TokenProvider: mockCLITokenProviderFailure}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one.") - } -} - -func TestBearerPolicy_AzureCLICredential(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - cred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TokenProvider: mockCLITokenProviderSuccess}) - if err != nil { - t.Fatalf("Did not expect an error but received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - _, err = pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - if err != nil { - t.Fatal("Expected nil error but received one") - } -} diff --git a/sdk/azidentity/bearer_token_policy.go b/sdk/azidentity/bearer_token_policy.go deleted file mode 100644 index e00d85d51524..000000000000 --- a/sdk/azidentity/bearer_token_policy.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "net/http" - "sync" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - bearerTokenPrefix = "Bearer " -) - -type bearerTokenPolicy struct { - // cond is used to synchronize token refresh. the locker - // must be locked when updating the following shared state. - cond *sync.Cond - - // renewing indicates that the token is in the process of being refreshed - renewing bool - - // header contains the authorization header value - header string - - // expiresOn is when the token will expire - expiresOn time.Time - - // the following fields are read-only - creds azcore.TokenCredential - options azcore.TokenRequestOptions -} - -func newBearerTokenPolicy(creds azcore.TokenCredential, opts azcore.AuthenticationPolicyOptions) *bearerTokenPolicy { - return &bearerTokenPolicy{ - cond: sync.NewCond(&sync.Mutex{}), - creds: creds, - options: opts.Options, - } -} - -func (b *bearerTokenPolicy) Do(ctx context.Context, req *azcore.Request) (*azcore.Response, error) { - if req.URL.Scheme != "https" { - // HTTPS must be used, otherwise the tokens are at the risk of being exposed - return nil, &AuthenticationFailedError{msg: "token credentials require a URL using the HTTPS protocol scheme"} - } - // create a "refresh window" before the token's real expiration date. - // this allows callers to continue to use the old token while the - // refresh is in progress. - const window = 2 * time.Minute - now, getToken, header := time.Now(), false, "" - // acquire exclusive lock - b.cond.L.Lock() - for { - if b.expiresOn.IsZero() || b.expiresOn.Before(now) { - // token was never obtained or has expired - if !b.renewing { - // another go routine isn't refreshing the token so this one will - b.renewing = true - getToken = true - break - } - // getting here means this go routine will wait for the token to refresh - } else if b.expiresOn.Add(-window).Before(now) { - // token is within the expiration window - if !b.renewing { - // another go routine isn't refreshing the token so this one will - b.renewing = true - getToken = true - break - } - // this go routine will use the existing token while another refreshes it - header = b.header - break - } else { - // token is not expiring yet so use it as-is - header = b.header - break - } - // wait for the token to refresh - b.cond.Wait() - } - b.cond.L.Unlock() - if getToken { - // this go routine has been elected to refresh the token - tk, err := b.creds.GetToken(ctx, b.options) - if err != nil { - return nil, err - } - header = bearerTokenPrefix + tk.Token - // update shared state - b.cond.L.Lock() - b.renewing = false - b.header = header - b.expiresOn = tk.ExpiresOn - // signal any waiters that the token has been refreshed - b.cond.Broadcast() - b.cond.L.Unlock() - } - req.Request.Header.Set(azcore.HeaderXmsDate, time.Now().UTC().Format(http.TimeFormat)) - req.Request.Header.Set(azcore.HeaderAuthorization, header) - return req.Next(ctx) -} diff --git a/sdk/azidentity/bearer_token_policy_test.go b/sdk/azidentity/bearer_token_policy_test.go deleted file mode 100644 index cbe167e62c38..000000000000 --- a/sdk/azidentity/bearer_token_policy_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "net/http" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -const ( - accessTokenRespError = `{"error": "invalid_client","error_description": "Invalid client secret is provided.","error_codes": [0],"timestamp": "2019-12-01 19:00:00Z","trace_id": "2d091b0","correlation_id": "a999","error_uri": "https://login.contoso.com/error?code=0"}` - accessTokenRespSuccess = `{"access_token": "` + tokenValue + `", "expires_in": 3600}` - accessTokenRespMalformed = `{"access_token": 0, "expires_in": 3600}` - accessTokenRespShortLived = `{"access_token": "` + tokenValue + `", "expires_in": 0}` -) - -func TestBearerPolicy_SuccessGetToken(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, secret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - resp, err := pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - if err != nil { - t.Fatalf("Expected nil error but received one") - } - const expectedToken = bearerTokenPrefix + tokenValue - if token := resp.Request.Header.Get(azcore.HeaderAuthorization); token != expectedToken { - t.Fatalf("expected token '%s', got '%s'", expectedToken, token) - } -} - -func TestBearerPolicy_CredentialFailGetToken(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusUnauthorized)) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, wrongSecret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - resp, err := pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - var afe *AuthenticationFailedError - if !errors.As(err, &afe) { - t.Fatalf("unexpected error type %v", err) - } - if resp != nil { - t.Fatal("expected nil response") - } -} - -func TestBearerTokenPolicy_TokenExpired(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespShortLived))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespShortLived))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespShortLived))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, secret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - req := azcore.NewRequest(http.MethodGet, srv.URL()) - _, err = pipeline.Do(context.Background(), req) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - _, err = pipeline.Do(context.Background(), req) - if err != nil { - t.Fatalf("unexpected error %v", err) - } -} - -// with https scheme enabled we get an auth failed error which let's us test the is not retriable error -func TestRetryPolicy_IsNotRetriable(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusUnauthorized)) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, wrongSecret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - _, err = pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - var afe *AuthenticationFailedError - if !errors.As(err, &afe) { - t.Fatalf("unexpected error type %v", err) - } -} - -func TestRetryPolicy_HTTPRequest(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, wrongSecret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - _, err = pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - var afe *AuthenticationFailedError - if !errors.As(err, &afe) { - t.Fatalf("unexpected error type %v", err) - } -} diff --git a/sdk/azidentity/chained_token_credential.go b/sdk/azidentity/chained_token_credential.go deleted file mode 100644 index b8bb15b00711..000000000000 --- a/sdk/azidentity/chained_token_credential.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// ChainedTokenCredential provides a TokenCredential implementation that chains multiple TokenCredential sources to be tried in order -// and returns the token from the first successful call to GetToken(). -type ChainedTokenCredential struct { - sources []azcore.TokenCredential -} - -// NewChainedTokenCredential creates an instance of ChainedTokenCredential with the specified TokenCredential sources. -func NewChainedTokenCredential(sources ...azcore.TokenCredential) (*ChainedTokenCredential, error) { - if len(sources) == 0 { - credErr := &CredentialUnavailableError{CredentialType: "Chained Token Credential", Message: "Length of sources cannot be 0"} - azcore.Log().Write(azcore.LogError, logCredentialError(credErr.CredentialType, credErr)) - return nil, credErr - } - for _, source := range sources { - if source == nil { // cannot have a nil credential in the chain or else the application will panic when GetToken() is called on nil - credErr := &CredentialUnavailableError{CredentialType: "Chained Token Credential", Message: "Sources cannot contain a nil TokenCredential"} - azcore.Log().Write(azcore.LogError, logCredentialError(credErr.CredentialType, credErr)) - return nil, credErr - } - } - return &ChainedTokenCredential{sources: sources}, nil -} - -// GetToken sequentially calls TokenCredential.GetToken on all the specified sources, returning the token from the first successful call to GetToken(). -func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts azcore.TokenRequestOptions) (token *azcore.AccessToken, err error) { - var errList []*CredentialUnavailableError - for _, cred := range c.sources { // loop through all of the credentials provided in sources - token, err = cred.GetToken(ctx, opts) // make a GetToken request for the current credential in the loop - var credErr *CredentialUnavailableError - if errors.As(err, &credErr) { // check if we received a CredentialUnavailableError - errList = append(errList, credErr) // if we did receive a CredentialUnavailableError then we append it to our error slice and continue looping for a good credential - } else if err != nil { // if we receive some other type of error then we must stop looping and process the error accordingly - var authenticationFailed *AuthenticationFailedError - if errors.As(err, &authenticationFailed) { // if the error is an AuthenticationFailedError we return the error related to the invalid credential and append all of the other error messages received prior to this point - authErr := &AuthenticationFailedError{msg: "Received an AuthenticationFailedError, there is an invalid credential in the chain. " + createChainedErrorMessage(errList), inner: err} - addGetTokenFailureLogs("Chained Token Credential", authErr) - return nil, authErr - } - addGetTokenFailureLogs("Chained Token Credential", err) - return nil, err // if we receive some other error type this is unexpected and we simple return the unexpected error - } else { - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - return token, nil // if we did not receive an error then we return the token - } - } - // if we reach this point it means that all of the credentials in the chain returned CredentialUnavailableErrors - credErr := &CredentialUnavailableError{CredentialType: "Chained Token Credential", Message: createChainedErrorMessage(errList)} - addGetTokenFailureLogs("Chained Token Credential", credErr) - return nil, credErr -} - -// AuthenticationPolicy implements the azcore.Credential interface on ChainedTokenCredential and sets the bearer token -func (c *ChainedTokenCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) -} - -// helper function used to chain the error messages of the CredentialUnavailableError slice -func createChainedErrorMessage(errList []*CredentialUnavailableError) string { - msg := "" - for _, err := range errList { - msg += err.Error() - } - - return msg -} diff --git a/sdk/azidentity/chained_token_credential_test.go b/sdk/azidentity/chained_token_credential_test.go deleted file mode 100644 index 96fd678bcacc..000000000000 --- a/sdk/azidentity/chained_token_credential_test.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "net/http" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -func TestChainedTokenCredential_InstantiateSuccess(t *testing.T) { - err := initEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Could not set environment variables for testing: %v", err) - } - secCred, err := NewClientSecretCredential(tenantID, clientID, secret, nil) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - envCred, err := NewEnvironmentCredential(nil) - if err != nil { - t.Fatalf("Could not find appropriate environment credentials") - } - cred, err := NewChainedTokenCredential(secCred, envCred) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if cred != nil { - if len(cred.sources) != 2 { - t.Fatalf("Expected 2 sources in the chained token credential, instead found %d", len(cred.sources)) - } - } -} - -func TestChainedTokenCredential_InstantiateFailure(t *testing.T) { - secCred, err := NewClientSecretCredential(tenantID, clientID, secret, nil) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = NewChainedTokenCredential(secCred, nil) - if err == nil { - t.Fatalf("Expected an error for sending a nil credential in the chain") - } - var credErr *CredentialUnavailableError - if !errors.As(err, &credErr) { - t.Fatalf("Expected a CredentialUnavailableError, but received: %T", credErr) - } - _, err = NewChainedTokenCredential() - if err == nil { - t.Fatalf("Expected an error for not sending any credential sources") - } - if !errors.As(err, &credErr) { - t.Fatalf("Expected a CredentialUnavailableError, but received: %T", credErr) - } -} - -func TestChainedTokenCredential_GetTokenSuccess(t *testing.T) { - err := initEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Could not set environment variables for testing: %v", err) - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - secCred, err := NewClientSecretCredential(tenantID, clientID, secret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - envCred, err := NewEnvironmentCredential(&TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Failed to create environment credential: %v", err) - } - cred, err := NewChainedTokenCredential(secCred, envCred) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - tk, err := cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - t.Fatalf("Received an error when attempting to get a token but expected none") - } - if tk.Token != tokenValue { - t.Fatalf("Received an incorrect access token") - } - if tk.ExpiresOn.IsZero() { - t.Fatalf("Received an incorrect time in the response") - } -} - -func TestChainedTokenCredential_GetTokenFail(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusUnauthorized)) - testURL := srv.URL() - secCred, err := NewClientSecretCredential(tenantID, clientID, wrongSecret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &testURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - cred, err := NewChainedTokenCredential(secCred) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one") - } - var authErr *AuthenticationFailedError - if !errors.As(err, &authErr) { - t.Fatalf("Expected Error Type: AuthenticationFailedError, ReceivedErrorType: %T", err) - } - if len(err.Error()) == 0 { - t.Fatalf("Did not create an appropriate error message") - } -} - -func TestChainedTokenCredential_GetTokenWithUnavailableCredentialInChain(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendError(&CredentialUnavailableError{CredentialType: "MockCredential", Message: "Mocking a credential unavailable error"}) - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - testURL := srv.URL() - secCred, err := NewClientSecretCredential(tenantID, clientID, wrongSecret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &testURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - // The chain has the same credential twice, since it doesn't matter what credential we add to the chain as long as it is not a nil credential. - // Most credentials will not be instantiated if the conditions do not exist to allow them to be used, thus returning a - // CredentialUnavailable error from the constructor. In order to test the CredentialUnavailable functionality for - // ChainedTokenCredential we have to mock with two valid credentials, but the first will fail since the first response queued - // in the test server is a CredentialUnavailable error. - cred, err := NewChainedTokenCredential(secCred, secCred) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - tk, err := cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - t.Fatalf("Received an error when attempting to get a token but expected none") - } - if tk.Token != tokenValue { - t.Fatalf("Received an incorrect access token") - } - if tk.ExpiresOn.IsZero() { - t.Fatalf("Received an incorrect time in the response") - } -} - -func TestBearerPolicy_ChainedTokenCredential(t *testing.T) { - err := initEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to initialize environment variables. Received: %v", err) - } - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, secret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - chainedCred, err := NewChainedTokenCredential(cred) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - chainedCred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - _, err = pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - if err != nil { - t.Fatalf("Expected an empty error but receive: %v", err) - } -} diff --git a/sdk/azidentity/client_certificate_credential.go b/sdk/azidentity/client_certificate_credential.go deleted file mode 100644 index 2626b09f7331..000000000000 --- a/sdk/azidentity/client_certificate_credential.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "os" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// ClientCertificateCredential enables authentication of a service principal to Azure Active Directory using a certificate that is assigned to its App Registration. More information -// on how to configure certificate authentication can be found here: -// https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad -type ClientCertificateCredential struct { - client *aadIdentityClient - tenantID string // The Azure Active Directory tenant (directory) ID of the service principal - clientID string // The client (application) ID of the service principal - clientCertificate string // Path to the client certificate generated for the App Registration used to authenticate the client -} - -// NewClientCertificateCredential creates an instance of ClientCertificateCredential with the details needed to authenticate against Azure Active Directory with the specified certificate. -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal. -// clientID: The client (application) ID of the service principal. -// clientCertificate: The path to the client certificate that was generated for the App Registration used to authenticate the client. -// options: configure the management of the requests sent to Azure Active Directory. -func NewClientCertificateCredential(tenantID string, clientID string, clientCertificate string, options *TokenCredentialOptions) (*ClientCertificateCredential, error) { - _, err := os.Stat(clientCertificate) - if err != nil { - credErr := &CredentialUnavailableError{CredentialType: "Client Certificate Credential", Message: "Certificate file not found in path: " + clientCertificate} - azcore.Log().Write(azcore.LogError, logCredentialError(credErr.CredentialType, credErr)) - return nil, credErr - } - c, err := newAADIdentityClient(options) - if err != nil { - return nil, err - } - return &ClientCertificateCredential{tenantID: tenantID, clientID: clientID, clientCertificate: clientCertificate, client: c}, nil -} - -// GetToken obtains a token from Azure Active Directory, using the certificate in the file path. -// scopes: The list of scopes for which the token will have access. -// ctx: controlling the request lifetime. -// Returns an AccessToken which can be used to authenticate service client calls. -func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts azcore.TokenRequestOptions) (*azcore.AccessToken, error) { - tk, err := c.client.authenticateCertificate(ctx, c.tenantID, c.clientID, c.clientCertificate, opts.Scopes) - if err != nil { - addGetTokenFailureLogs("Client Certificate Credential", err) - return nil, err - } - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - return tk, nil -} - -// AuthenticationPolicy implements the azcore.Credential interface on ClientSecretCredential. -func (c *ClientCertificateCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) -} diff --git a/sdk/azidentity/client_certificate_credential_test.go b/sdk/azidentity/client_certificate_credential_test.go deleted file mode 100644 index fe7f60d47f87..000000000000 --- a/sdk/azidentity/client_certificate_credential_test.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "io/ioutil" - "net/http" - "net/url" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -const ( - certificatePath = "testdata/certificate.pem" - wrongCertificatePath = "wrong_certificate_path.pem" -) - -func TestClientCertificateCredential_CreateAuthRequestSuccess(t *testing.T) { - cred, err := NewClientCertificateCredential(tenantID, clientID, certificatePath, nil) - if err != nil { - t.Fatalf("Failed to instantiate credential") - } - req, err := cred.client.createClientCertificateAuthRequest(cred.tenantID, cred.clientID, cred.clientCertificate, []string{scope}) - if err != nil { - t.Fatalf("Unexpectedly received an error: %v", err) - } - if req.Request.Header.Get(azcore.HeaderContentType) != azcore.HeaderURLEncoded { - t.Fatalf("Unexpected value for Content-Type header") - } - body, err := ioutil.ReadAll(req.Request.Body) - if err != nil { - t.Fatalf("Unable to read request body") - } - bodyStr := string(body) - reqQueryParams, err := url.ParseQuery(bodyStr) - if err != nil { - t.Fatalf("Unable to parse query params in request") - } - if reqQueryParams[qpClientID][0] != clientID { - t.Fatalf("Unexpected client ID in the client_id header") - } - if reqQueryParams[qpGrantType][0] != "client_credentials" { - t.Fatalf("Wrong grant type in request body") - } - if reqQueryParams[qpClientAssertionType][0] != clientAssertionType { - t.Fatalf("Wrong client assertion type assigned to request") - } - if reqQueryParams[qpScope][0] != scope { - t.Fatalf("Unexpected scope in scope header") - } - if len(reqQueryParams[qpClientAssertion][0]) == 0 { - t.Fatalf("Client assertion is not present on the request") - } - if req.Request.URL.Host != defaultTestAuthorityHost { - t.Fatalf("Unexpected default authority host") - } - if req.Request.URL.Scheme != "https" { - t.Fatalf("Wrong request scheme") - } -} - -func TestClientCertificateCredential_GetTokenSuccess(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - cred, err := NewClientCertificateCredential(tenantID, clientID, certificatePath, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } -} - -func TestClientCertificateCredential_GetTokenInvalidCredentials(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.SetResponse(mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - cred, err := NewClientCertificateCredential(tenantID, clientID, certificatePath, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Did not expect an error but received one: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected to receive a nil error, but received: %v", err) - } - var authFailed *AuthenticationFailedError - if !errors.As(err, &authFailed) { - t.Fatalf("Expected: AuthenticationFailedError, Received: %T", err) - } -} - -func TestClientCertificateCredential_WrongCertificatePath(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.SetResponse(mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - _, err := NewClientCertificateCredential(tenantID, clientID, wrongCertificatePath, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err == nil { - t.Fatalf("Expected an error but did not receive one") - } -} - -func TestClientCertificateCredential_GetTokenCheckPrivateKeyBlocks(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - cred, err := NewClientCertificateCredential(tenantID, clientID, "testdata/certificate_formatB.pem", &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } -} - -func TestClientCertificateCredential_GetTokenCheckCertificateBlocks(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - cred, err := NewClientCertificateCredential(tenantID, clientID, "testdata/certificate_formatA.pem", &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } -} - -func TestClientCertificateCredential_GetTokenEmptyCertificate(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - cred, err := NewClientCertificateCredential(tenantID, clientID, "testdata/certificate_empty.pem", &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected an error but received nil") - } -} - -func TestClientCertificateCredential_GetTokenNoPrivateKey(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - cred, err := NewClientCertificateCredential(tenantID, clientID, "testdata/certificate_nokey.pem", &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected an error but received nil") - } -} - -func TestBearerPolicy_ClientCertificateCredential(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - cred, err := NewClientCertificateCredential(tenantID, clientID, certificatePath, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Did not expect an error but received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - _, err = pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - if err != nil { - t.Fatalf("Expected nil error but received one") - } -} diff --git a/sdk/azidentity/client_secret_credential.go b/sdk/azidentity/client_secret_credential.go deleted file mode 100644 index eb0e39aa94e5..000000000000 --- a/sdk/azidentity/client_secret_credential.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// ClientSecretCredential enables authentication to Azure Active Directory using a client secret that was generated for an App Registration. More information on how -// to configure a client secret can be found here: -// https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application -type ClientSecretCredential struct { - client *aadIdentityClient - tenantID string // Gets the Azure Active Directory tenant (directory) ID of the service principal - clientID string // Gets the client (application) ID of the service principal - clientSecret string // Gets the client secret that was generated for the App Registration used to authenticate the client. -} - -// NewClientSecretCredential constructs a new ClientSecretCredential with the details needed to authenticate against Azure Active Directory with a client secret. -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal. -// clientID: The client (application) ID of the service principal. -// clientSecret: A client secret that was generated for the App Registration used to authenticate the client. -// options: allow to configure the management of the requests sent to Azure Active Directory. -func NewClientSecretCredential(tenantID string, clientID string, clientSecret string, options *TokenCredentialOptions) (*ClientSecretCredential, error) { - c, err := newAADIdentityClient(options) - if err != nil { - return nil, err - } - return &ClientSecretCredential{tenantID: tenantID, clientID: clientID, clientSecret: clientSecret, client: c}, nil -} - -// GetToken obtains a token from Azure Active Directory, using the specified client secret to authenticate. -// ctx: Context used to control the request lifetime. -// opts: TokenRequestOptions contains the list of scopes for which the token will have access. -// Returns an AccessToken which can be used to authenticate service client calls. -func (c *ClientSecretCredential) GetToken(ctx context.Context, opts azcore.TokenRequestOptions) (*azcore.AccessToken, error) { - tk, err := c.client.authenticate(ctx, c.tenantID, c.clientID, c.clientSecret, opts.Scopes) - if err != nil { - addGetTokenFailureLogs("Client Secret Credential", err) - return nil, err - } - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - return tk, nil -} - -// AuthenticationPolicy implements the azcore.Credential interface on ClientSecretCredential and calls the Bearer Token policy -// to get the bearer token. -func (c *ClientSecretCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) -} - -var _ azcore.TokenCredential = (*ClientSecretCredential)(nil) diff --git a/sdk/azidentity/client_secret_credential_test.go b/sdk/azidentity/client_secret_credential_test.go deleted file mode 100644 index 007c9b695e61..000000000000 --- a/sdk/azidentity/client_secret_credential_test.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "io/ioutil" - "net/http" - "net/url" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -const ( - tenantID = "expected_tenant" - clientID = "expected_client" - secret = "secret" - wrongSecret = "wrong_secret" - tokenValue = "new_token" - scope = "http://storage.azure.com/.default" - defaultTestAuthorityHost = "login.microsoftonline.com" -) - -func TestClientSecretCredential_CreateAuthRequestSuccess(t *testing.T) { - cred, err := NewClientSecretCredential(tenantID, clientID, secret, nil) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - req, err := cred.client.createClientSecretAuthRequest(cred.tenantID, cred.clientID, cred.clientSecret, []string{scope}) - if err != nil { - t.Fatalf("Unexpectedly received an error: %v", err) - } - if req.Request.Header.Get(azcore.HeaderContentType) != azcore.HeaderURLEncoded { - t.Fatalf("Unexpected value for Content-Type header") - } - body, err := ioutil.ReadAll(req.Request.Body) - if err != nil { - t.Fatalf("Unable to read request body") - } - bodyStr := string(body) - reqQueryParams, err := url.ParseQuery(bodyStr) - if err != nil { - t.Fatalf("Unable to parse query params in request") - } - if reqQueryParams[qpClientID][0] != clientID { - t.Fatalf("Unexpected client ID in the client_id header") - } - if reqQueryParams[qpClientSecret][0] != secret { - t.Fatalf("Unexpected secret in the client_secret header") - } - if reqQueryParams[qpScope][0] != scope { - t.Fatalf("Unexpected scope in scope header") - } - if req.Request.URL.Host != defaultTestAuthorityHost { - t.Fatalf("Unexpected default authority host") - } - if req.Request.URL.Scheme != "https" { - t.Fatalf("Wrong request scheme") - } -} - -func TestClientSecretCredential_GetTokenSuccess(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, secret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - t.Fatalf("Expected an empty error but received: %v", err) - } -} - -func TestClientSecretCredential_GetTokenInvalidCredentials(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.SetResponse(mock.WithBody([]byte(accessTokenRespError)), mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, wrongSecret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one.") - } - var authFailed *AuthenticationFailedError - if !errors.As(err, &authFailed) { - t.Fatalf("Expected: AuthenticationFailedError, Received: %T", err) - } else { - var respError *AADAuthenticationFailedError - if !errors.As(authFailed.Unwrap(), &respError) { - t.Fatalf("Expected: AADAuthenticationFailedError, Received: %T", err) - } else { - if len(respError.Message) == 0 { - t.Fatalf("Did not receive an error message") - } - if len(respError.Description) == 0 { - t.Fatalf("Did not receive an error description") - } - if len(respError.Timestamp) == 0 { - t.Fatalf("Did not receive a timestamp") - } - if len(respError.TraceID) == 0 { - t.Fatalf("Did not receive a TraceID") - } - if len(respError.CorrelationID) == 0 { - t.Fatalf("Did not receive a CorrelationID") - } - if len(respError.URI) == 0 { - t.Fatalf("Did not receive an error URI") - } - if respError.Response == nil { - t.Fatalf("Did not receive an error response") - } - } - } -} - -func TestClientSecretCredential_GetTokenUnexpectedJSON(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespMalformed))) - srvURL := srv.URL() - cred, err := NewClientSecretCredential(tenantID, clientID, secret, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Failed to create the credential") - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected a JSON marshal error but received nil") - } -} diff --git a/sdk/azidentity/default_azure_credential.go b/sdk/azidentity/default_azure_credential.go deleted file mode 100644 index 1bcd0c0d4e01..000000000000 --- a/sdk/azidentity/default_azure_credential.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - developerSignOnClientID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" -) - -// DefaultAzureCredentialOptions contains options for configuring how credentials are acquired. -type DefaultAzureCredentialOptions struct { - // set this field to true in order to exclude the EnvironmentCredential from the set of - // credentials that will be used to authenticate with - ExcludeEnvironmentCredential bool - // set this field to true in order to exclude the ManagedIdentityCredential from the set of - // credentials that will be used to authenticate with - ExcludeMSICredential bool -} - -// NewDefaultAzureCredential provides a default ChainedTokenCredential configuration for applications that will be deployed to Azure. The following credential -// types will be tried, in the following order: -// - EnvironmentCredential -// - ManagedIdentityCredential -// Consult the documentation for these credential types for more information on how they attempt authentication. -func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*ChainedTokenCredential, error) { - var creds []azcore.TokenCredential - errMsg := "" - - if options == nil { - options = &DefaultAzureCredentialOptions{} - } - - if !options.ExcludeEnvironmentCredential { - envCred, err := NewEnvironmentCredential(nil) - if err == nil { - creds = append(creds, envCred) - } else { - errMsg += err.Error() - } - } - - if !options.ExcludeMSICredential { - msiCred, err := NewManagedIdentityCredential("", nil) - if err == nil { - creds = append(creds, msiCred) - } else { - errMsg += err.Error() - } - } - // if no credentials are added to the slice of TokenCredentials then return a CredentialUnavailableError - if len(creds) == 0 { - err := &CredentialUnavailableError{CredentialType: "Default Azure Credential", Message: errMsg} - azcore.Log().Write(azcore.LogError, logCredentialError(err.CredentialType, err)) - return nil, err - } - azcore.Log().Write(LogCredential, "Azure Identity => NewDefaultAzureCredential() invoking NewChainedTokenCredential()") - return NewChainedTokenCredential(creds...) -} diff --git a/sdk/azidentity/default_azure_credential_test.go b/sdk/azidentity/default_azure_credential_test.go deleted file mode 100644 index 37299019f594..000000000000 --- a/sdk/azidentity/default_azure_credential_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "os" - "testing" -) - -func TestDefaultAzureCredential_ExcludeEnvCredential(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - _ = os.Setenv("MSI_ENDPOINT", "http://localhost:3000") - cred, err := NewDefaultAzureCredential(&DefaultAzureCredentialOptions{ExcludeEnvironmentCredential: true}) - if err != nil { - t.Fatalf("Did not expect to receive an error in creating the credential") - } - - if len(cred.sources) != 1 { - t.Fatalf("Length of ChainedTokenCredential sources for DefaultAzureCredential. Expected: 1, Received: %d", len(cred.sources)) - } - _ = os.Setenv("MSI_ENDPOINT", "") - -} - -func TestDefaultAzureCredential_ExcludeMSICredential(t *testing.T) { - err := initEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - cred, err := NewDefaultAzureCredential(&DefaultAzureCredentialOptions{ExcludeMSICredential: true}) - if err != nil { - t.Fatalf("Did not expect to receive an error in creating the credential") - } - if len(cred.sources) != 1 { - t.Fatalf("Length of ChainedTokenCredential sources for DefaultAzureCredential. Expected: 1, Received: %d", len(cred.sources)) - } - -} - -func TestDefaultAzureCredential_ExcludeAllCredentials(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - var credUnavailable *CredentialUnavailableError - _, err = NewDefaultAzureCredential(&DefaultAzureCredentialOptions{ExcludeEnvironmentCredential: false, ExcludeMSICredential: true}) - if err == nil { - t.Fatalf("Expected an error but received nil") - } - if !errors.As(err, &credUnavailable) { - t.Fatalf("Expected: CredentialUnavailableError, Received: %T", err) - } - -} - -func TestDefaultAzureCredential_NilOptions(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - err = initEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - cred, err := NewDefaultAzureCredential(nil) - if err != nil { - t.Fatalf("Did not expect to receive an error in creating the credential") - } - c := newManagedIdentityClient(nil) - // if the test is running in a MSI environment then the length of sources would be two since it will include environmnet credential and managed identity credential - if msiType, err := c.getMSIType(context.Background()); msiType == msiTypeIMDS || msiType == msiTypeCloudShell || msiType == msiTypeAppService { - if len(cred.sources) != 2 { - t.Fatalf("Length of ChainedTokenCredential sources for DefaultAzureCredential. Expected: 2, Received: %d", len(cred.sources)) - } - //if a credential unavailable error is received or msiType is unknown then only the environment credential will be added - } else if unavailableErr := (*CredentialUnavailableError)(nil); errors.As(err, &unavailableErr) || msiType == msiTypeUnknown { - if len(cred.sources) != 1 { - t.Fatalf("Length of ChainedTokenCredential sources for DefaultAzureCredential. Expected: 1, Received: %d", len(cred.sources)) - } - // if there is some other unexpected error then we fail here - } else if err != nil { - t.Fatalf("Received an error when trying to determine MSI type: %v", err) - } -} diff --git a/sdk/azidentity/device_code_credential.go b/sdk/azidentity/device_code_credential.go deleted file mode 100644 index 43c6767823d7..000000000000 --- a/sdk/azidentity/device_code_credential.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - deviceCodeGrantType = "urn:ietf:params:oauth:grant-type:device_code" -) - -// DeviceCodeCredential authenticates a user using the device code flow, and provides access tokens for that user account. -// For more information on the device code authentication flow see: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code. -type DeviceCodeCredential struct { - client *aadIdentityClient - tenantID string // Gets the Azure Active Directory tenant (directory) ID of the service principal - clientID string // Gets the client (application) ID of the service principal - callback func(string) // Sends the user a message with a verification URL and device code to sign in to the login server - refreshToken string // Gets the refresh token sent from the service and will be used to retreive new access tokens after the initial request for a token. Thread safety for updates is handled in the AuthenticationPolicy since only one goroutine will be updating at a time -} - -// NewDeviceCodeCredential constructs a new DeviceCodeCredential used to authenticate against Azure Active Directory with a device code. -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal. If none is set then the default value ("organizations") will be used in place of the tenantID. -// clientID: The client (application) ID of the service principal. -// callback: The callback function used to send the login message back to the user -// options: Options used to configure the management of the requests sent to Azure Active Directory. -func NewDeviceCodeCredential(tenantID string, clientID string, callback func(string), options *TokenCredentialOptions) (*DeviceCodeCredential, error) { - c, err := newAADIdentityClient(options) - if err != nil { - return nil, err - } - return &DeviceCodeCredential{tenantID: tenantID, clientID: clientID, callback: callback, client: c}, nil -} - -// GetToken obtains a token from Azure Active Directory, following the device code authentication -// flow. This function first requests a device code and requests that the user login before continuing to authenticate the device. -// This function will keep polling the service for a token until the user logs in. -// scopes: The list of scopes for which the token will have access. The "offline_access" scope is checked for and automatically added in case it isn't present to allow for silent token refresh. -// ctx: The context for controlling the request lifetime. -// Returns an AccessToken which can be used to authenticate service client calls. -func (c *DeviceCodeCredential) GetToken(ctx context.Context, opts azcore.TokenRequestOptions) (*azcore.AccessToken, error) { - for i, scope := range opts.Scopes { - if scope == "offline_access" { // if we find that the opts.Scopes slice contains "offline_access" then we don't need to do anything and exit - break - } - if i == len(opts.Scopes)-1 && scope != "offline_access" { // if we haven't found "offline_access" when reaching the last element in the slice then we append it - opts.Scopes = append(opts.Scopes, "offline_access") - } - } - if len(c.refreshToken) != 0 { - tk, err := c.client.refreshAccessToken(ctx, c.tenantID, c.clientID, "", c.refreshToken, opts.Scopes) - if err != nil { - addGetTokenFailureLogs("Device Code Credential", err) - return nil, err - } - // assign new refresh token to the credential for future use - c.refreshToken = tk.refreshToken - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - // passing the access token and/or error back up - return tk.token, nil - } - // if there is no refreshToken, then begin the Device Code flow from the beginning - // make initial request to the device code endpoint for a device code and instructions for authentication - dc, err := c.client.requestNewDeviceCode(ctx, c.tenantID, c.clientID, opts.Scopes) - if err != nil { - addGetTokenFailureLogs("Device Code Credential", err) - return nil, err // TODO check what error type to return here - } - // send authentication flow instructions back to the user to log in and authorize the device - c.callback(dc.Message) - // poll the token endpoint until a valid access token is received or until authentication fails - for { - tk, err := c.client.authenticateDeviceCode(ctx, c.tenantID, c.clientID, dc.DeviceCode, opts.Scopes) - // if there is no error, save the refresh token and return the token credential - if err == nil { - c.refreshToken = tk.refreshToken - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - return tk.token, err - } - // if there is an error, check for an AADAuthenticationFailedError in order to check the status for token retrieval - // if the error is not an AADAuthenticationFailedError, then fail here since something unexpected occurred - if authRespErr := (*AADAuthenticationFailedError)(nil); errors.As(err, &authRespErr) && authRespErr.Message == "authorization_pending" { - // wait for the interval specified from the initial device code endpoint and then poll for the token again - time.Sleep(time.Duration(dc.Interval) * time.Second) - } else { - addGetTokenFailureLogs("Device Code Credential", err) - // any other error should be returned - return nil, err - } - } -} - -// AuthenticationPolicy implements the azcore.Credential interface on ClientSecretCredential. -func (c *DeviceCodeCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) -} - -// deviceCodeResult is used to store device code related information to help the user login and allow the device code flow to continue -// to request a token to authenticate a user -type deviceCodeResult struct { - UserCode string `json:"user_code"` // User code returned by the service - DeviceCode string `json:"device_code"` // Device code returned by the service - VerificationURL string `json:"verification_uri"` // Verification URL where the user must navigate to authenticate using the device code and credentials. - Interval int64 `json:"interval"` // Polling interval time to check for completion of authentication flow. - Message string `json:"message"` // User friendly text response that can be used for display purpose. -} diff --git a/sdk/azidentity/device_code_credential_test.go b/sdk/azidentity/device_code_credential_test.go deleted file mode 100644 index 4e131e772452..000000000000 --- a/sdk/azidentity/device_code_credential_test.go +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "errors" - "io/ioutil" - "net/http" - "net/url" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -const ( - deviceCode = "device_code" - deviceCodeResponse = `{"user_code":"test_code","device_code":"test_device_code","verification_uri":"https://microsoft.com/devicelogin","expires_in":900,"interval":5,"message":"To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code test_code to authenticate."}` - deviceCodeScopes = "user.read offline_access openid profile email" - authorizationPendingResponse = `{"error": "authorization_pending","error_description": "Authorization pending.","error_codes": [],"timestamp": "2019-12-01 19:00:00Z","trace_id": "2d091b0","correlation_id": "a999","error_uri": "https://login.contoso.com/error?code=0"}` - expiredTokenResponse = `{"error": "expired_token","error_description": "Token has expired.","error_codes": [],"timestamp": "2019-12-01 19:00:00Z","trace_id": "2d091b0","correlation_id": "a999","error_uri": "https://login.contoso.com/error?code=0"}` -) - -func TestDeviceCodeCredential_CreateAuthRequestSuccess(t *testing.T) { - handler := func(s string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, nil) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - req, err := cred.client.createDeviceCodeAuthRequest(cred.tenantID, cred.clientID, deviceCode, []string{deviceCodeScopes}) - if err != nil { - t.Fatalf("Unexpectedly received an error: %v", err) - } - if req.Request.Header.Get(azcore.HeaderContentType) != azcore.HeaderURLEncoded { - t.Fatalf("Unexpected value for Content-Type header") - } - body, err := ioutil.ReadAll(req.Request.Body) - if err != nil { - t.Fatalf("Unable to read request body") - } - bodyStr := string(body) - reqQueryParams, err := url.ParseQuery(bodyStr) - if err != nil { - t.Fatalf("Unable to parse query params in request") - } - if reqQueryParams[qpGrantType][0] != deviceCodeGrantType { - t.Fatalf("Unexpected grant type") - } - if reqQueryParams[qpClientID][0] != clientID { - t.Fatalf("Unexpected client ID in the client_id header") - } - if reqQueryParams[qpDeviceCode][0] != deviceCode { - t.Fatalf("Unexpected username in the username header") - } - if reqQueryParams[qpScope][0] != deviceCodeScopes { - t.Fatalf("Unexpected scope in scope header") - } - if req.Request.URL.Host != defaultTestAuthorityHost { - t.Fatalf("Unexpected default authority host") - } - if req.Request.URL.Scheme != "https" { - t.Fatalf("Wrong request scheme") - } -} - -func TestDeviceCodeCredential_CreateAuthRequestEmptyTenant(t *testing.T) { - handler := func(s string) {} - cred, err := NewDeviceCodeCredential("", clientID, handler, nil) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - req, err := cred.client.createDeviceCodeAuthRequest(cred.tenantID, cred.clientID, deviceCode, []string{deviceCodeScopes}) - if err != nil { - t.Fatalf("Unexpectedly received an error: %v", err) - } - if req.Request.Header.Get(azcore.HeaderContentType) != azcore.HeaderURLEncoded { - t.Fatalf("Unexpected value for Content-Type header") - } - body, err := ioutil.ReadAll(req.Request.Body) - if err != nil { - t.Fatalf("Unable to read request body") - } - bodyStr := string(body) - reqQueryParams, err := url.ParseQuery(bodyStr) - if err != nil { - t.Fatalf("Unable to parse query params in request") - } - if reqQueryParams[qpGrantType][0] != deviceCodeGrantType { - t.Fatalf("Unexpected grant type") - } - if reqQueryParams[qpClientID][0] != clientID { - t.Fatalf("Unexpected client ID in the client_id header") - } - if reqQueryParams[qpDeviceCode][0] != deviceCode { - t.Fatalf("Unexpected username in the username header") - } - if reqQueryParams[qpScope][0] != deviceCodeScopes { - t.Fatalf("Unexpected scope in scope header") - } - if req.Request.URL.Host != defaultTestAuthorityHost { - t.Fatalf("Unexpected default authority host") - } - if req.Request.URL.Scheme != "https" { - t.Fatalf("Wrong request scheme") - } - if req.Request.URL.Path != "/organizations/oauth2/v2.0/token" { - t.Fatalf("Did not set the right path when passing in an empty tenant ID") - } -} - -func TestDeviceCodeCredential_RequestNewDeviceCodeEmptyTenant(t *testing.T) { - handler := func(s string) {} - cred, err := NewDeviceCodeCredential("", clientID, handler, nil) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - req, err := cred.client.createDeviceCodeNumberRequest(cred.tenantID, cred.clientID, []string{deviceCodeScopes}) - if err != nil { - t.Fatalf("Unexpectedly received an error: %v", err) - } - if req.Request.Header.Get(azcore.HeaderContentType) != azcore.HeaderURLEncoded { - t.Fatalf("Unexpected value for Content-Type header") - } - body, err := ioutil.ReadAll(req.Request.Body) - if err != nil { - t.Fatalf("Unable to read request body") - } - bodyStr := string(body) - reqQueryParams, err := url.ParseQuery(bodyStr) - if err != nil { - t.Fatalf("Unable to parse query params in request") - } - if reqQueryParams[qpClientID][0] != clientID { - t.Fatalf("Unexpected client ID in the client_id header") - } - if reqQueryParams[qpScope][0] != deviceCodeScopes { - t.Fatalf("Unexpected scope in scope header") - } - if req.Request.URL.Host != defaultTestAuthorityHost { - t.Fatalf("Unexpected default authority host") - } - if req.Request.URL.Scheme != "https" { - t.Fatalf("Wrong request scheme") - } - if req.Request.URL.Path != "/organizations/oauth2/v2.0/devicecode" { - t.Fatalf("Did not set the right path when passing in an empty tenant ID") - } -} - -func TestDeviceCodeCredential_GetTokenSuccess(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(deviceCodeResponse))) - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - handler := func(string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - tk, err := cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{deviceCodeScopes}}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } - if tk.Token != "new_token" { - t.Fatalf("Received an unexpected value in azcore.AccessToken.Token") - } -} - -func TestDeviceCodeCredential_GetTokenInvalidCredentials(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.SetResponse(mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - handler := func(string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{deviceCodeScopes}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one.") - } -} - -func TestDeviceCodeCredential_GetTokenAuthorizationPending(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(deviceCodeResponse))) - srv.AppendResponse(mock.WithBody([]byte(authorizationPendingResponse)), mock.WithStatusCode(http.StatusUnauthorized)) - srv.AppendResponse(mock.WithBody([]byte(authorizationPendingResponse)), mock.WithStatusCode(http.StatusUnauthorized)) - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - handler := func(string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{deviceCodeScopes}}) - if err != nil { - t.Fatalf("Expected an empty error but received %v", err) - } -} - -func TestDeviceCodeCredential_GetTokenExpiredToken(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(deviceCodeResponse))) - srv.AppendResponse(mock.WithBody([]byte(authorizationPendingResponse)), mock.WithStatusCode(http.StatusUnauthorized)) - srv.AppendResponse(mock.WithBody([]byte(expiredTokenResponse)), mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - handler := func(string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{deviceCodeScopes}}) - if err == nil { - t.Fatalf("Expected an error but received none") - } -} - -func TestDeviceCodeCredential_GetTokenWithRefreshTokenFailure(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespError)), mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - handler := func(string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - cred.refreshToken = "refresh_token" - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{deviceCodeScopes}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one") - } - var aadErr *AADAuthenticationFailedError - if !errors.As(err, &aadErr) { - t.Fatalf("Did not receive an AADAuthenticationFailedError but was expecting one") - } -} - -func TestDeviceCodeCredential_GetTokenWithRefreshTokenSuccess(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - handler := func(string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - cred.refreshToken = "refresh_token" - tk, err := cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{deviceCodeScopes}}) - if err != nil { - t.Fatalf("Received an unexpected error: %s", err.Error()) - } - if tk.Token != "new_token" { - t.Fatalf("Unexpected value for token") - } -} - -func TestBearerPolicy_DeviceCodeCredential(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(deviceCodeResponse))) - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - handler := func(string) {} - cred, err := NewDeviceCodeCredential(tenantID, clientID, handler, &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{deviceCodeScopes}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - req := azcore.NewRequest(http.MethodGet, srv.URL()) - _, err = pipeline.Do(context.Background(), req) - if err != nil { - t.Fatalf("Expected an empty error but receive: %v", err) - } -} diff --git a/sdk/azidentity/environment_credential.go b/sdk/azidentity/environment_credential.go deleted file mode 100644 index 936e840792e3..000000000000 --- a/sdk/azidentity/environment_credential.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "os" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// NewEnvironmentCredential creates an instance of the ClientSecretCredential type and reads credential details from environment variables. -// If the expected environment variables are not found at this time, then a CredentialUnavailableError will be returned. -// options: The options used to configure the management of the requests sent to Azure Active Directory. -func NewEnvironmentCredential(options *TokenCredentialOptions) (*ClientSecretCredential, error) { - tenantID := os.Getenv("AZURE_TENANT_ID") - if tenantID == "" { - err := &CredentialUnavailableError{CredentialType: "Environment Credential", Message: "Missing environment variable AZURE_TENANT_ID"} - azcore.Log().Write(azcore.LogError, logCredentialError(err.CredentialType, err)) - return nil, err - } - - clientID := os.Getenv("AZURE_CLIENT_ID") - if clientID == "" { - err := &CredentialUnavailableError{CredentialType: "Environment Credential", Message: "Missing environment variable AZURE_CLIENT_ID"} - azcore.Log().Write(azcore.LogError, logCredentialError(err.CredentialType, err)) - return nil, err - } - - clientSecret := os.Getenv("AZURE_CLIENT_SECRET") - if clientSecret == "" { - err := &CredentialUnavailableError{CredentialType: "Environment Credential", Message: "Missing environment variable AZURE_CLIENT_SECRET"} - azcore.Log().Write(azcore.LogError, logCredentialError(err.CredentialType, err)) - return nil, err - } - azcore.Log().Write(LogCredential, "Azure Identity => NewEnvironmentCredential() invoking ClientSecretCredential") - return NewClientSecretCredential(tenantID, clientID, clientSecret, options) -} diff --git a/sdk/azidentity/environment_credential_test.go b/sdk/azidentity/environment_credential_test.go deleted file mode 100644 index 53885baedf60..000000000000 --- a/sdk/azidentity/environment_credential_test.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "errors" - "os" - "testing" -) - -func initEnvironmentVarsForTest() error { - err := os.Setenv("AZURE_TENANT_ID", tenantID) - if err != nil { - return err - } - err = os.Setenv("AZURE_CLIENT_ID", clientID) - if err != nil { - return err - } - err = os.Setenv("AZURE_CLIENT_SECRET", secret) - if err != nil { - return err - } - return nil -} - -func resetEnvironmentVarsForTest() error { - err := os.Setenv("AZURE_TENANT_ID", "") - if err != nil { - return err - } - err = os.Setenv("AZURE_CLIENT_ID", "") - if err != nil { - return err - } - err = os.Setenv("AZURE_CLIENT_SECRET", "") - if err != nil { - return err - } - return nil -} - -func TestEnvironmentCredential_TenantIDNotSet(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - err = os.Setenv("AZURE_CLIENT_ID", clientID) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - err = os.Setenv("AZURE_CLIENT_SECRET", secret) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - _, err = NewEnvironmentCredential(nil) - if err == nil { - t.Fatalf("Expected an error but received nil") - } - var credentialUnavailable *CredentialUnavailableError - if !errors.As(err, &credentialUnavailable) { - t.Fatalf("Expected a credential unavailable error, instead received: %T", err) - } -} - -func TestEnvironmentCredential_ClientIDNotSet(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - err = os.Setenv("AZURE_TENANT_ID", tenantID) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - err = os.Setenv("AZURE_CLIENT_SECRET", secret) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - _, err = NewEnvironmentCredential(nil) - if err == nil { - t.Fatalf("Expected an error but received nil") - } - var credentialUnavailable *CredentialUnavailableError - if !errors.As(err, &credentialUnavailable) { - t.Fatalf("Expected a credential unavailable error, instead received: %T", err) - } -} - -func TestEnvironmentCredential_ClientSecretNotSet(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - err = os.Setenv("AZURE_TENANT_ID", tenantID) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - err = os.Setenv("AZURE_CLIENT_ID", clientID) - if err != nil { - t.Fatalf("Unexpected error when initializing environment variables: %v", err) - } - _, err = NewEnvironmentCredential(nil) - if err == nil { - t.Fatalf("Expected an error but received nil") - } - var credentialUnavailable *CredentialUnavailableError - if !errors.As(err, &credentialUnavailable) { - t.Fatalf("Expected a credential unavailable error, instead received: %T", err) - } -} diff --git a/sdk/azidentity/fingerprint.go b/sdk/azidentity/fingerprint.go deleted file mode 100644 index b047293078d6..000000000000 --- a/sdk/azidentity/fingerprint.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "bufio" - "bytes" - "crypto/sha1" - "encoding/pem" - "errors" - "fmt" - "os" -) - -// fingerprint type wraps a byte slice that contains the corresponding SHA-1 fingerprint for the client's certificate -type fingerprint []byte - -// String represents the fingerprint digest as a series of -// colon-delimited hexadecimal octets. -func (f fingerprint) String() string { - var buf bytes.Buffer - for i, b := range f { - if i > 0 { - fmt.Fprintf(&buf, ":") - } - fmt.Fprintf(&buf, "%02x", b) - } - return buf.String() -} - -// spkiFingerprint calculates the fingerprint of the certificate based on it's Subject Public Key Info with the SHA-1 -// signing algorithm. -func spkiFingerprint(cert string) (fingerprint, error) { - privateKeyFile, err := os.Open(cert) - if err != nil { - return nil, fmt.Errorf("%s: %w", cert, err) - } - defer privateKeyFile.Close() - - pemFileInfo, err := privateKeyFile.Stat() - if err != nil { - return nil, err - } - - var size int64 = pemFileInfo.Size() - pemBytes := make([]byte, size) - buffer := bufio.NewReader(privateKeyFile) - _, err = buffer.Read(pemBytes) - if err != nil { - return nil, err - } - // Get first block of PEM file - data, rest := pem.Decode([]byte(pemBytes)) - const certificateBlock = "CERTIFICATE" - if data.Type != certificateBlock { - for len(rest) > 0 { - data, rest = pem.Decode(rest) - if data.Type == certificateBlock { - // Sign the CERTIFICATE block with SHA1 - h := sha1.New() - _, err := h.Write(data.Bytes) - if err != nil { - return nil, err - } - - return fingerprint(h.Sum(nil)), nil - } - } - return nil, errors.New("Cannot find CERTIFICATE in file") - } - h := sha1.New() - _, err = h.Write(data.Bytes) - if err != nil { - return nil, err - } - - return fingerprint(h.Sum(nil)), nil -} diff --git a/sdk/azidentity/go.mod b/sdk/azidentity/go.mod deleted file mode 100644 index ec84ba11f6ce..000000000000 --- a/sdk/azidentity/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/Azure/azure-sdk-for-go/sdk/azidentity - -go 1.13 - -require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 - github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0 -) diff --git a/sdk/azidentity/go.sum b/sdk/azidentity/go.sum deleted file mode 100644 index 00dfdfebed95..000000000000 --- a/sdk/azidentity/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 h1:VdhfbVpQ3dkhXYOx/Wj1+utikcZkZSZSmpqmXWwaNJY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0/go.mod h1:hL9TGc07RkJVzDIBxsYXC/r0M+YiRkvl4z1elXCD+8s= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0 h1:cLpVMIkXC/umSP9DMz9I6FttDWJAsmvhpaB6MlkagGY= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= diff --git a/sdk/azidentity/jwt.go b/sdk/azidentity/jwt.go deleted file mode 100644 index 320e598b2809..000000000000 --- a/sdk/azidentity/jwt.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "encoding/base64" - "encoding/json" - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" -) - -// headerJWT type contains the fields necessary to create a JSON Web Token including the x5t field which must contain a x.509 certificate thumbprint -type headerJWT struct { - Typ string `json:"typ"` - Alg string `json:"alg"` - X5t string `json:"x5t"` -} - -// payloadJWT type contains all fields that are necessary when creating a JSON Web Token payload section -type payloadJWT struct { - JTI string `json:"jti"` - AUD string `json:"aud"` - ISS string `json:"iss"` - SUB string `json:"sub"` - NBF int64 `json:"nbf"` - EXP int64 `json:"exp"` -} - -// createClientAssertionJWT build the JWT header, payload and signature, -// then returns a string for the JWT assertion -func createClientAssertionJWT(clientID string, audience string, clientCertificate string) (string, error) { - // TODO: open cert file here and pass to spkiFingerprint and getPrivateKey - fingerprint, err := spkiFingerprint(clientCertificate) - if err != nil { - return "", err - } - - headerData := headerJWT{ - Typ: "JWT", - Alg: "RS256", - X5t: base64.RawURLEncoding.EncodeToString(fingerprint), - } - - headerJSON, err := json.Marshal(headerData) - if err != nil { - return "", fmt.Errorf("Marshal headerJWT: %w", err) - } - header := base64.RawURLEncoding.EncodeToString(headerJSON) - - payloadData := payloadJWT{ - JTI: uuid.New().String(), - AUD: audience, - ISS: clientID, - SUB: clientID, - NBF: time.Now().Unix(), - EXP: time.Now().Add(30 * time.Minute).Unix(), - } - - payloadJSON, err := json.Marshal(payloadData) - if err != nil { - return "", fmt.Errorf("Marshal payloadJWT: %w", err) - } - payload := base64.RawURLEncoding.EncodeToString(payloadJSON) - result := header + "." + payload - hashed := []byte(result) - hashedSum := sha256.Sum256(hashed) - cryptoRand := rand.Reader - - privateKey, err := getPrivateKey(clientCertificate) - if err != nil { - return "", err - } - - signed, err := rsa.SignPKCS1v15(cryptoRand, privateKey, crypto.SHA256, hashedSum[:]) - if err != nil { - return "", err - } - - signature := base64.RawURLEncoding.EncodeToString(signed) - - return result + "." + signature, nil -} diff --git a/sdk/azidentity/logging.go b/sdk/azidentity/logging.go deleted file mode 100644 index 4e6ca943c000..000000000000 --- a/sdk/azidentity/logging.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "fmt" - "os" - "strings" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// LogCredential is the log classification that can be used for logging Azure Identity related information -const LogCredential azcore.LogClassification = "credential" - -// log environment variables that can be used for credential types -func logEnvVars() { - if !azcore.Log().Should(LogCredential) { - return - } - // Log available environment variables - envVars := []string{} - if envCheck := os.Getenv("AZURE_TENANT_ID"); len(envCheck) > 0 { - envVars = append(envVars, "AZURE_TENANT_ID") - } - if envCheck := os.Getenv("AZURE_CLIENT_ID"); len(envCheck) > 0 { - envVars = append(envVars, "AZURE_CLIENT_ID") - } - if envCheck := os.Getenv("AZURE_CLIENT_SECRET"); len(envCheck) > 0 { - envVars = append(envVars, "AZURE_CLIENT_SECRET") - } - if envCheck := os.Getenv("AZURE_AUTHORITY_HOST"); len(envCheck) > 0 { - envVars = append(envVars, "AZURE_AUTHORITY_HOST") - } - if envCheck := os.Getenv("AZURE_CLI_PATH"); len(envCheck) > 0 { - envVars = append(envVars, "AZURE_CLI_PATH") - } - if len(envVars) > 0 { - azcore.Log().Write(LogCredential, fmt.Sprintf("Azure Identity => Found the following environment variables: %s", strings.Join(envVars, ", "))) - } -} - -func logGetTokenSuccess(cred azcore.TokenCredential, opts azcore.TokenRequestOptions) string { - msg := fmt.Sprintf("Azure Identity => GetToken() result for %T: SUCCESS\n", cred) - msg += fmt.Sprintf("Azure Identity => Scopes: [%s]", strings.Join(opts.Scopes, ", ")) - return msg -} - -func logGetTokenFailure(credName string) string { - return fmt.Sprintf("Azure Identity => ERROR in GetToken() call for %s. Please check the log for the error.", credName) -} - -func logCredentialError(credName string, err error) string { - return fmt.Sprintf("Azure Identity => ERROR in %s: %s", credName, err.Error()) -} - -func logMSIEnv(msi msiType) string { - switch msi { - case 1: - return "Azure Identity => Managed Identity environment: IMDS" - case 2: - return "Azure Identity => Managed Identity environment: MSI_ENDPOINT" - case 3: - return "Azure Identity => Managed Identity environment: MSI_ENDPOINT" - case 4: - return "Azure Identity => Managed Identity environment: Unavailable" - default: - return "Azure Identity => Managed Identity environment: Unknown" - } -} - -func addGetTokenFailureLogs(credName string, err error) { - azcore.Log().Write(azcore.LogError, logCredentialError(credName, err)) - azcore.Log().Write(azcore.LogError, logGetTokenFailure(credName)) -} diff --git a/sdk/azidentity/managed_identity_client.go b/sdk/azidentity/managed_identity_client.go deleted file mode 100644 index 7fc1dbf19dff..000000000000 --- a/sdk/azidentity/managed_identity_client.go +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/url" - "os" - "strconv" - "strings" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - imdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token" -) - -const ( - msiEndpointEnvironemntVariable = "MSI_ENDPOINT" - msiSecretEnvironemntVariable = "MSI_SECRET" - appServiceMsiAPIVersion = "2017-09-01" - imdsAPIVersion = "2018-02-01" -) - -type msiType int - -const ( - msiTypeUnknown msiType = 0 - msiTypeIMDS msiType = 1 - msiTypeAppService msiType = 2 - msiTypeCloudShell msiType = 3 - msiTypeUnavailable msiType = 4 -) - -// managedIdentityClient provides the base for authenticating in managed identity environments -// This type includes an azcore.Pipeline and TokenCredentialOptions. -type managedIdentityClient struct { - pipeline azcore.Pipeline - imdsAPIVersion string - imdsAvailableTimeoutMS time.Duration - msiType msiType - endpoint *url.URL -} - -type wrappedNumber json.Number - -func (n *wrappedNumber) UnmarshalJSON(b []byte) error { - c := string(b) - if c == "\"\"" { - return nil - } - return json.Unmarshal(b, (*json.Number)(n)) -} - -var ( - imdsURL *url.URL // these are initialized in the init func and are R/O afterwards - defaultMSIOpts = newDefaultManagedIdentityOptions() -) - -func init() { - // The error is checked for in managed_identity_client_test.go and should not be ignored if the test fails - imdsURL, _ = url.Parse(imdsEndpoint) -} - -func newDefaultManagedIdentityOptions() *ManagedIdentityCredentialOptions { - return &ManagedIdentityCredentialOptions{ - HTTPClient: azcore.DefaultHTTPClientTransport(), - } -} - -// newManagedIdentityClient creates a new instance of the ManagedIdentityClient with the ManagedIdentityCredentialOptions -// that are passed into it along with a default pipeline. -// options: ManagedIdentityCredentialOptions configure policies for the pipeline and the authority host that -// will be used to retrieve tokens and authenticate -func newManagedIdentityClient(options *ManagedIdentityCredentialOptions) *managedIdentityClient { - logEnvVars() - options = options.setDefaultValues() - return &managedIdentityClient{ - pipeline: newDefaultMSIPipeline(*options), // a pipeline that includes the specific requirements for MSI authentication, such as custom retry policy options - imdsAPIVersion: imdsAPIVersion, // this field will be set to whatever value exists in the constant and is used when creating requests to IMDS - imdsAvailableTimeoutMS: 500, // we allow a timeout of 500 ms since the endpoint might be slow to respond - msiType: msiTypeUnknown, // when creating a new managedIdentityClient, the current MSI type is unknown and will be tested for and replaced once authenticate() is called from GetToken on the credential side - } -} - -// authenticate creates an authentication request for a Managed Identity and returns the resulting Access Token if successful. -// ctx: The current context for controlling the request lifetime. -// clientID: The client (application) ID of the service principal. -// scopes: The scopes required for the token. -func (c *managedIdentityClient) authenticate(ctx context.Context, clientID string, scopes []string) (*azcore.AccessToken, error) { - currentMSI, err := c.getMSIType(ctx) - if err != nil { - return nil, err - } - // This condition should never be true since getMSIType returns an error in these cases - // if MSI is unavailable or we were unable to determine the type return a nil access token - if currentMSI == msiTypeUnavailable || currentMSI == msiTypeUnknown { - return nil, &CredentialUnavailableError{CredentialType: "Managed Identity Credential", Message: "Please make sure you are running in a managed identity environment, such as a VM, Azure Functions, Cloud Shell, etc..."} - } - - AT, err := c.sendAuthRequest(ctx, currentMSI, clientID, scopes) - if err != nil { - return nil, err - } - return AT, nil -} - -func (c *managedIdentityClient) sendAuthRequest(ctx context.Context, msiType msiType, clientID string, scopes []string) (*azcore.AccessToken, error) { - msg, err := c.createAuthRequest(msiType, clientID, scopes) - if err != nil { - return nil, err - } - - resp, err := c.pipeline.Do(ctx, msg) - if err != nil { - return nil, err - } - - if resp.HasStatusCode(successStatusCodes[:]...) { - return c.createAccessToken(resp) - } - - return nil, &AuthenticationFailedError{inner: newAADAuthenticationFailedError(resp)} -} - -func (c *managedIdentityClient) createAccessToken(res *azcore.Response) (*azcore.AccessToken, error) { - value := struct { - // these are the only fields that we use - Token string `json:"access_token,omitempty"` - RefreshToken string `json:"refresh_token,omitempty"` - ExpiresIn wrappedNumber `json:"expires_in,omitempty"` // this field should always return the number of seconds for which a token is valid - ExpiresOn string `json:"expires_on,omitempty"` // the value returned in this field varies between a number and a date string - }{} - if err := res.UnmarshalAsJSON(&value); err != nil { - return nil, fmt.Errorf("internal AccessToken: %w", err) - } - if value.ExpiresIn != "" { - expiresIn, err := json.Number(value.ExpiresIn).Int64() - if err != nil { - return nil, err - } - return &azcore.AccessToken{Token: value.Token, ExpiresOn: time.Now().Add(time.Second * time.Duration(expiresIn)).UTC()}, nil - } - if expiresOn, err := strconv.Atoi(value.ExpiresOn); err == nil { - return &azcore.AccessToken{Token: value.Token, ExpiresOn: time.Now().Add(time.Second * time.Duration(expiresOn)).UTC()}, nil - } - // this is the case when expires_on is a time string - // this is the format of the string coming from the service - if expiresOn, err := time.Parse("01/02/2006 15:04:05 PM +00:00", value.ExpiresOn); err == nil { // the date string specified in the layout param of time.Parse cannot be changed, Golang expects whatever layout to always signify January 2, 2006 at 3:04 PM - eo := expiresOn.UTC() - return &azcore.AccessToken{Token: value.Token, ExpiresOn: eo}, nil - } else { - return nil, err - } -} - -func (c *managedIdentityClient) createAuthRequest(msiType msiType, clientID string, scopes []string) (*azcore.Request, error) { - switch msiType { - case msiTypeIMDS: - return c.createIMDSAuthRequest(scopes), nil - case msiTypeAppService: - return c.createAppServiceAuthRequest(clientID, scopes), nil - case msiTypeCloudShell: - return c.createCloudShellAuthRequest(clientID, scopes) - default: - errorMsg := "" - switch msiType { - case msiTypeUnavailable: - errorMsg = "unavailable" - default: - errorMsg = "unknown" - } - - return nil, &CredentialUnavailableError{CredentialType: "Managed Identity Credential", Message: "Make sure you are running in a valid Managed Identity Environment. Status: " + errorMsg} - } -} - -func (c *managedIdentityClient) createIMDSAuthRequest(scopes []string) *azcore.Request { - request := azcore.NewRequest(http.MethodGet, *c.endpoint) - request.Header.Set(azcore.HeaderMetadata, "true") - q := request.URL.Query() - q.Add("api-version", c.imdsAPIVersion) - q.Add("resource", strings.Join(scopes, " ")) - request.URL.RawQuery = q.Encode() - - return request -} - -func (c *managedIdentityClient) createAppServiceAuthRequest(clientID string, scopes []string) *azcore.Request { - request := azcore.NewRequest(http.MethodGet, *c.endpoint) - request.Header.Set("secret", os.Getenv(msiSecretEnvironemntVariable)) - q := request.URL.Query() - q.Add("api-version", appServiceMsiAPIVersion) - q.Add("resource", strings.Join(scopes, " ")) - if clientID != "" { - q.Add(qpClientID, clientID) - } - request.URL.RawQuery = q.Encode() - - return request -} - -func (c *managedIdentityClient) createCloudShellAuthRequest(clientID string, scopes []string) (*azcore.Request, error) { - request := azcore.NewRequest(http.MethodPost, *c.endpoint) - request.Header.Set(azcore.HeaderContentType, azcore.HeaderURLEncoded) - request.Header.Set(azcore.HeaderMetadata, "true") - data := url.Values{} - data.Set("resource", strings.Join(scopes, " ")) - if clientID != "" { - data.Set("client_id", clientID) - } - dataEncoded := data.Encode() - body := azcore.NopCloser(strings.NewReader(dataEncoded)) - err := request.SetBody(body) - if err != nil { - return nil, err - } - return request, nil -} - -func (c *managedIdentityClient) getMSIType(ctx context.Context) (msiType, error) { - if c.msiType == msiTypeUnknown { // if we haven't already determined the msi type - if endpointEnvVar := os.Getenv(msiEndpointEnvironemntVariable); endpointEnvVar != "" { // if the env var MSI_ENDPOINT is set - endpoint, err := url.Parse(endpointEnvVar) - if err != nil { - return msiTypeUnknown, err - } - c.endpoint = endpoint - if secretEnvVar := os.Getenv(msiSecretEnvironemntVariable); secretEnvVar != "" { // if BOTH the env vars MSI_ENDPOINT and MSI_SECRET are set the MsiType is AppService - c.msiType = msiTypeAppService - } else { // if ONLY the env var MSI_ENDPOINT is set the MsiType is CloudShell - c.msiType = msiTypeCloudShell - } - } else if c.imdsAvailable(ctx) { // if MSI_ENDPOINT is NOT set AND the IMDS endpoint is available the MsiType is Imds. This will timeout after 500 milliseconds - c.endpoint = imdsURL - c.msiType = msiTypeIMDS - } else { // if MSI_ENDPOINT is NOT set and IMDS enpoint is not available ManagedIdentity is not available - c.msiType = msiTypeUnavailable - return c.msiType, &CredentialUnavailableError{CredentialType: "Managed Identity Credential", Message: "Make sure you are running in a valid Managed Identity Environment"} - } - } - return c.msiType, nil -} - -func (c *managedIdentityClient) imdsAvailable(ctx context.Context) bool { - tempCtx, cancel := context.WithTimeout(ctx, c.imdsAvailableTimeoutMS*time.Millisecond) - defer cancel() - request := azcore.NewRequest(http.MethodGet, *imdsURL) - q := request.URL.Query() - q.Add("api-version", c.imdsAPIVersion) - request.URL.RawQuery = q.Encode() - _, err := c.pipeline.Do(tempCtx, request) - return err == nil -} diff --git a/sdk/azidentity/managed_identity_client_test.go b/sdk/azidentity/managed_identity_client_test.go deleted file mode 100644 index f38461c495ad..000000000000 --- a/sdk/azidentity/managed_identity_client_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "net/url" - "testing" -) - -func TestIMDSEndpointParse(t *testing.T) { - _, err := url.Parse(imdsEndpoint) - if err != nil { - t.Fatalf("Failed to parse the IMDS endpoint: %v", err) - } -} - -// func TestNewDefaultMSIPipeline(t *testing.T) { -// p := newDefaultMSIPipeline(ManagedIdentityCredentialOptions{}) -// } diff --git a/sdk/azidentity/managed_identity_credential.go b/sdk/azidentity/managed_identity_credential.go deleted file mode 100644 index a20c277332fa..000000000000 --- a/sdk/azidentity/managed_identity_credential.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "os" - "strings" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// ManagedIdentityCredentialOptions contains parameters that can be used to configure the pipeline used with Managed Identity Credential. -type ManagedIdentityCredentialOptions struct { - // HTTPClient sets the transport for making HTTP requests. - // Leave this as nil to use the default HTTP transport. - HTTPClient azcore.Transport - - // LogOptions configures the built-in request logging policy behavior. - LogOptions azcore.RequestLogOptions - - // Telemetry configures the built-in telemetry policy behavior. - Telemetry azcore.TelemetryOptions -} - -func (m *ManagedIdentityCredentialOptions) setDefaultValues() *ManagedIdentityCredentialOptions { - if m == nil { - m = defaultMSIOpts - } - return m -} - -// ManagedIdentityCredential attempts authentication using a managed identity that has been assigned to the deployment environment. This authentication type works in several -// managed identity environments such as Azure VMs, App Service, Azure Functions, Azure CloudShell, among others. More information about configuring managed identities can be found here: -// https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview -type ManagedIdentityCredential struct { - clientID string - client *managedIdentityClient -} - -// NewManagedIdentityCredential creates an instance of the ManagedIdentityCredential capable of authenticating a resource that has a managed identity. -// clientID: The client ID to authenticate for a user assigned managed identity. -// options: ManagedIdentityCredentialOptions that configure the pipeline for requests sent to Azure Active Directory. -// More information on user assigned managed identities cam be found here: -// https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview#how-a-user-assigned-managed-identity-works-with-an-azure-vm -func NewManagedIdentityCredential(clientID string, options *ManagedIdentityCredentialOptions) (*ManagedIdentityCredential, error) { - // Create a new Managed Identity Client with default options - client := newManagedIdentityClient(options) - // Create a context that will timeout after 500 milliseconds (that is the amount of time designated to find out if the IMDS endpoint is available) - ctx, cancelFunc := context.WithTimeout(context.Background(), time.Duration(client.imdsAvailableTimeoutMS)*time.Millisecond) - defer cancelFunc() - msiType, err := client.getMSIType(ctx) - // If there is an error that means that the code is not running in a Managed Identity environment - if err != nil { - credErr := &CredentialUnavailableError{CredentialType: "Managed Identity Credential", Message: "Please make sure you are running in a managed identity environment, such as a VM, Azure Functions, Cloud Shell, etc..."} - azcore.Log().Write(azcore.LogError, logCredentialError(credErr.CredentialType, credErr)) - return nil, credErr - } - // Assign the msiType discovered onto the client - client.msiType = msiType - // check if no clientID is specified then check if it exists in an environment variable - if len(clientID) == 0 { - clientID = os.Getenv("AZURE_CLIENT_ID") - } - return &ManagedIdentityCredential{clientID: clientID, client: client}, nil -} - -// GetToken obtains an AccessToken from the Managed Identity service if available. -// scopes: The list of scopes for which the token will have access. -// Returns an AccessToken which can be used to authenticate service client calls. -func (c *ManagedIdentityCredential) GetToken(ctx context.Context, opts azcore.TokenRequestOptions) (*azcore.AccessToken, error) { - tk, err := c.client.authenticate(ctx, c.clientID, opts.Scopes) - if err != nil { - addGetTokenFailureLogs("Managed Identity Credential", err) - return nil, err - } - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - azcore.Log().Write(LogCredential, logMSIEnv(c.client.msiType)) - return tk, err -} - -// AuthenticationPolicy implements the azcore.Credential interface on ManagedIdentityCredential. -// Please note: the TokenRequestOptions included in AuthenticationPolicyOptions must be a slice of resources in this case and not scopes -func (c *ManagedIdentityCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - // The following code will remove the /.default suffix from any scopes passed into the method since ManagedIdentityCredentials expect a resource string instead of a scope string - for i := range options.Options.Scopes { - options.Options.Scopes[i] = strings.TrimSuffix(options.Options.Scopes[i], defaultSuffix) - } - return newBearerTokenPolicy(c, options) -} diff --git a/sdk/azidentity/managed_identity_credential_test.go b/sdk/azidentity/managed_identity_credential_test.go deleted file mode 100644 index 5177fb3475e1..000000000000 --- a/sdk/azidentity/managed_identity_credential_test.go +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "net/http" - "net/url" - "os" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -const ( - msiScope = "https://storage.azure.com" - appServiceTokenSuccessResp = `{"access_token": "new_token", "expires_on": "09/14/2017 00:00:00 PM +00:00", "resource": "https://vault.azure.net", "token_type": "Bearer"}` - expiresOnIntResp = `{"access_token": "new_token", "refresh_token": "", "expires_in": "", "expires_on": "1560974028", "not_before": "1560970130", "resource": "https://vault.azure.net", "token_type": "Bearer"}` -) - -func TestManagedIdentityCredential_GetTokenInCloudShellLive(t *testing.T) { - if len(os.Getenv("MSI_ENDPOINT")) == 0 { - t.Skip() - } - msiCred, err := NewManagedIdentityCredential(clientID, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err != nil { - t.Fatalf("Received an error when attempting to retrieve a token") - } -} - -func TestManagedIdentityCredential_GetTokenInCloudShellMock(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - msiCred, err := NewManagedIdentityCredential(clientID, &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err != nil { - t.Fatalf("Received an error when attempting to retrieve a token") - } -} - -func TestManagedIdentityCredential_GetTokenInCloudShellMockFail(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusUnauthorized)) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - msiCred, err := NewManagedIdentityCredential("", &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one") - } -} - -func TestManagedIdentityCredential_GetTokenInAppServiceMock(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(appServiceTokenSuccessResp))) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - _ = os.Setenv("MSI_SECRET", "secret") - msiCred, err := NewManagedIdentityCredential(clientID, &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err != nil { - t.Fatalf("Received an error when attempting to retrieve a token") - } -} - -func TestManagedIdentityCredential_CreateAccessTokenExpiresOnInt(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(expiresOnIntResp))) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - _ = os.Setenv("MSI_SECRET", "secret") - msiCred, err := NewManagedIdentityCredential(clientID, &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err != nil { - t.Fatalf("Received an error when attempting to retrieve a token") - } -} - -func TestManagedIdentityCredential_GetTokenInAppServiceMockFail(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusUnauthorized)) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - _ = os.Setenv("MSI_SECRET", "secret") - msiCred, err := NewManagedIdentityCredential("", &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one") - } -} - -// func TestManagedIdentityCredential_GetTokenIMDSMock(t *testing.T) { -// timeout := time.After(5 * time.Second) -// done := make(chan bool) -// go func() { -// err := resetEnvironmentVarsForTest() -// if err != nil { -// t.Fatalf("Unable to set environment variables") -// } -// srv, close := mock.NewServer() -// defer close() -// srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) -// msiCred := NewManagedIdentityCredential("", &ManagedIdentityCredentialOptions{HTTPClient: srv}) -// _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) -// if err == nil { -// t.Fatalf("Cannot run IMDS test in this environment") -// } -// time.Sleep(550 * time.Millisecond) -// done <- true -// }() - -// select { -// case <-timeout: -// t.Fatal("Test didn't finish in time") -// case <-done: -// } -// } - -func TestManagedIdentityCredential_NewManagedIdentityCredentialFail(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithStatusCode(http.StatusUnauthorized)) - _ = os.Setenv("MSI_ENDPOINT", "https://t .com") - _, err = NewManagedIdentityCredential("", &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err == nil { - t.Fatalf("Expected an error but did not receive one") - } -} - -func TestBearerPolicy_ManagedIdentityCredential(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - cred, err := NewManagedIdentityCredential(clientID, &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{msiScope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - _, err = pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - if err != nil { - t.Fatalf("Expected an empty error but receive: %v", err) - } -} - -func TestManagedIdentityCredential_GetTokenUnexpectedJSON(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespMalformed))) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - msiCred, err := NewManagedIdentityCredential(clientID, &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - _, err = msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err == nil { - t.Fatalf("Expected a JSON marshal error but received nil") - } -} - -func TestManagedIdentityCredential_CreateIMDSAuthRequest(t *testing.T) { - cred, err := NewManagedIdentityCredential(clientID, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - cred.client.endpoint = imdsURL - req := cred.client.createIMDSAuthRequest([]string{msiScope}) - if req.Request.Header.Get(azcore.HeaderMetadata) != "true" { - t.Fatalf("Unexpected value for Content-Type header") - } - reqQueryParams, err := url.ParseQuery(req.URL.RawQuery) - if err != nil { - t.Fatalf("Unable to parse IMDS query params: %v", err) - } - if reqQueryParams["api-version"][0] != imdsAPIVersion { - t.Fatalf("Unexpected IMDS API version") - } - if reqQueryParams["resource"][0] != msiScope { - t.Fatalf("Unexpected resource in resource query param") - } - if req.Request.URL.Host != imdsURL.Host { - t.Fatalf("Unexpected default authority host") - } - if req.Request.URL.Scheme != "http" { - t.Fatalf("Wrong request scheme") - } -} - -func TestManagedIdentityCredential_GetTokenEnvVar(t *testing.T) { - err := resetEnvironmentVarsForTest() - if err != nil { - t.Fatalf("Unable to set environment variables") - } - err = os.Setenv("AZURE_CLIENT_ID", "test_client_id") - if err != nil { - t.Fatal(err) - } - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - testURL := srv.URL() - _ = os.Setenv("MSI_ENDPOINT", testURL.String()) - msiCred, err := NewManagedIdentityCredential("", &ManagedIdentityCredentialOptions{HTTPClient: srv}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - at, err := msiCred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{msiScope}}) - if err != nil { - t.Fatalf("Received an error when attempting to retrieve a token") - } - if at.Token != "new_token" { - t.Fatalf("Did not receive the correct access token") - } -} diff --git a/sdk/azidentity/testdata/certificate.pem b/sdk/azidentity/testdata/certificate.pem deleted file mode 100644 index 4b66bfa021a0..000000000000 --- a/sdk/azidentity/testdata/certificate.pem +++ /dev/null @@ -1,49 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDL1hG+JYCfIPp3 -tlZ05J4pYIJ3Ckfs432bE3rYuWlR2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRY -OCI69s4+lP3DwR8uBCp9xyVkF8thXfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+Qf -oxAb6tx0kEc7V3ozBLWoIDJjfwJ3NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIr -Aa7pxHzo/Nd0U3e7z+DlBcJV7dY6TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bC -lG0u7unS7QOBMd6bOGkeL+Bc+n22slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpX -wj/Ek0F7AgMBAAECggEAblU3UWdXUcs2CCqIbcl52wfEVs8X05/n01MeAcWKvqYG -hvGcz7eLvhir5dQoXcF3VhybMrIe6C4WcBIiZSxGwxU+rwEP8YaLwX1UPfOrQM7s -sZTdFTLWfUslO3p7q300fdRA92iG9COMDZvkElh0cBvQksxs9sSr149l9vk+ymtC -uBhZtHG6Ki0BIMBNC9jGUqDuOatXl/dkK4tNjXrNJT7tVwzPaqnNALIWl6B+k9oQ -m1oNhSH2rvs9tw2ITXfIoIk9KdOMjQVUD43wKOaz0hNZhUsb1OFuls7UtRzaFcZH -rMd/M8DtA104QTTlHK+XS7r+nqdv7+ZyB+suTdM+oQKBgQDxCrJZU3hJ0eJ4VYhK -xGDfVGNpYxNkQ4CDB9fwRNbFr/Ck3kgzfE9QxTx1pJOolVmfuFmk9B86in4UNy91 -KdaqT79AU5RdOBXNN6tuMbLC0AVqe8sZq+1vWVVwbCstffxEMmyW1Ju/FLYPl2Zp -e5P96dBh5B3mXrQtpDJ0RkxxaQKBgQDYfE6tQQnQSs2ewD6ae8Mu6j8ueDlVoZ37 -vze1QdBasR26xu2H8XBt3u41zc524BwQsB1GE1tnC8ZylrqwVEayK4FesSQRCO6o -yK8QSdb06I5J4TaN+TppCDPLzstOh0Dmxp+iFUGoErb7AEOLAJ/VebhF9kBZObL/ -HYy4Es+bQwKBgHW/4vYuB3IQXNCp/+V+X1BZ+iJOaves3gekekF+b2itFSKFD8JO -9LQhVfKmTheptdmHhgtF0keXxhV8C+vxX1Ndl7EF41FSh5vzmQRAtPHkCvFEviex -TFD70/gSb1lO1UA/Xbqk69yBcprVPAtFejss0EYx2MVj+CLftmIEwW0ZAoGBAIMG -EVQ45eikLXjkn78+Iq7VZbIJX6IdNBH29I+GqsUJJ5Yw6fh6P3KwF3qG+mvmTfYn -sUAFXS+r58rYwVsRVsxlGmKmUc7hmhibhaEVH72QtvWuEiexbRG+viKfIVuA7t39 -3wXpWZiQ4yBdU4Pgt9wrVEU7ukyGaHiReOa7s90jAoGAJc0K7smn98YutQQ+g2ur -ybfnsl0YdsksaP2S2zvZUmNevKPrgnaIDDabOlhYYga+AK1G3FQ7/nefUgiIg1Nd -kr+T6Q4osS3xHB6Az9p/jaF4R2KaWN2nNVCn7ecsmPxDdM7k1vLxaT26vwO9OP5f -YU/5CeIzrfA5nQyPZkOXZBk= ------END PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUF2VIP4+AnEtb52KTCHbo4+fESfswDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTEwMzAyMjQ2MjBaFw0yMjA4 -MTkyMjQ2MjBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDL1hG+JYCfIPp3tlZ05J4pYIJ3Ckfs432bE3rYuWlR -2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRYOCI69s4+lP3DwR8uBCp9xyVkF8th -XfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+QfoxAb6tx0kEc7V3ozBLWoIDJjfwJ3 -NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIrAa7pxHzo/Nd0U3e7z+DlBcJV7dY6 -TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bClG0u7unS7QOBMd6bOGkeL+Bc+n22 -slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpXwj/Ek0F7AgMBAAGjUzBRMB0GA1Ud -DgQWBBT6Mf9uXFB67bY2PeW3GCTKfkO7vDAfBgNVHSMEGDAWgBT6Mf9uXFB67bY2 -PeW3GCTKfkO7vDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCZ -1+kTISX85v9/ag7glavaPFUYsOSOOofl8gSzov7L01YL+srq7tXdvZmWrjQ/dnOY -h18rp9rb24vwIYxNioNG/M2cW1jBJwEGsDPOwdPV1VPcRmmUJW9kY130gRHBCd/N -qB7dIkcQnpNsxPIIWI+sRQp73U0ijhOByDnCNHLHon6vbfFTwkO1XggmV5BdZ3uQ -JNJyckILyNzlhmf6zhonMp4lVzkgxWsAm2vgdawd6dmBa+7Avb2QK9s+IdUSutFh -DgW2L12Obgh12Y4sf1iKQXA0RbZ2k+XQIz8EKZa7vJQY0ciYXSgB/BV3a96xX3cx -LIPL8Vam8Ytkopi3gsGA ------END CERTIFICATE----- \ No newline at end of file diff --git a/sdk/azidentity/testdata/certificate_empty.pem b/sdk/azidentity/testdata/certificate_empty.pem deleted file mode 100644 index 24fc8011f2a7..000000000000 --- a/sdk/azidentity/testdata/certificate_empty.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN BLOCK----- -MIIDazCCAlOgAwIBAgIUF2VIP4+AnEtb52KTCHbo4+fESfswDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTEwMzAyMjQ2MjBaFw0yMjA4 -MTkyMjQ2MjBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDL1hG+JYCfIPp3tlZ05J4pYIJ3Ckfs432bE3rYuWlR -2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRYOCI69s4+lP3DwR8uBCp9xyVkF8th -XfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+QfoxAb6tx0kEc7V3ozBLWoIDJjfwJ3 -NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIrAa7pxHzo/Nd0U3e7z+DlBcJV7dY6 -TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bClG0u7unS7QOBMd6bOGkeL+Bc+n22 -slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpXwj/Ek0F7AgMBAAGjUzBRMB0GA1Ud -DgQWBBT6Mf9uXFB67bY2PeW3GCTKfkO7vDAfBgNVHSMEGDAWgBT6Mf9uXFB67bY2 -PeW3GCTKfkO7vDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCZ -1+kTISX85v9/ag7glavaPFUYsOSOOofl8gSzov7L01YL+srq7tXdvZmWrjQ/dnOY -h18rp9rb24vwIYxNioNG/M2cW1jBJwEGsDPOwdPV1VPcRmmUJW9kY130gRHBCd/N -qB7dIkcQnpNsxPIIWI+sRQp73U0ijhOByDnCNHLHon6vbfFTwkO1XggmV5BdZ3uQ -JNJyckILyNzlhmf6zhonMp4lVzkgxWsAm2vgdawd6dmBa+7Avb2QK9s+IdUSutFh -DgW2L12Obgh12Y4sf1iKQXA0RbZ2k+XQIz8EKZa7vJQY0ciYXSgB/BV3a96xX3cx -LIPL8Vam8Ytkopi3gsGA ------END BLOCK----- \ No newline at end of file diff --git a/sdk/azidentity/testdata/certificate_formatA.pem b/sdk/azidentity/testdata/certificate_formatA.pem deleted file mode 100644 index 4b66bfa021a0..000000000000 --- a/sdk/azidentity/testdata/certificate_formatA.pem +++ /dev/null @@ -1,49 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDL1hG+JYCfIPp3 -tlZ05J4pYIJ3Ckfs432bE3rYuWlR2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRY -OCI69s4+lP3DwR8uBCp9xyVkF8thXfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+Qf -oxAb6tx0kEc7V3ozBLWoIDJjfwJ3NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIr -Aa7pxHzo/Nd0U3e7z+DlBcJV7dY6TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bC -lG0u7unS7QOBMd6bOGkeL+Bc+n22slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpX -wj/Ek0F7AgMBAAECggEAblU3UWdXUcs2CCqIbcl52wfEVs8X05/n01MeAcWKvqYG -hvGcz7eLvhir5dQoXcF3VhybMrIe6C4WcBIiZSxGwxU+rwEP8YaLwX1UPfOrQM7s -sZTdFTLWfUslO3p7q300fdRA92iG9COMDZvkElh0cBvQksxs9sSr149l9vk+ymtC -uBhZtHG6Ki0BIMBNC9jGUqDuOatXl/dkK4tNjXrNJT7tVwzPaqnNALIWl6B+k9oQ -m1oNhSH2rvs9tw2ITXfIoIk9KdOMjQVUD43wKOaz0hNZhUsb1OFuls7UtRzaFcZH -rMd/M8DtA104QTTlHK+XS7r+nqdv7+ZyB+suTdM+oQKBgQDxCrJZU3hJ0eJ4VYhK -xGDfVGNpYxNkQ4CDB9fwRNbFr/Ck3kgzfE9QxTx1pJOolVmfuFmk9B86in4UNy91 -KdaqT79AU5RdOBXNN6tuMbLC0AVqe8sZq+1vWVVwbCstffxEMmyW1Ju/FLYPl2Zp -e5P96dBh5B3mXrQtpDJ0RkxxaQKBgQDYfE6tQQnQSs2ewD6ae8Mu6j8ueDlVoZ37 -vze1QdBasR26xu2H8XBt3u41zc524BwQsB1GE1tnC8ZylrqwVEayK4FesSQRCO6o -yK8QSdb06I5J4TaN+TppCDPLzstOh0Dmxp+iFUGoErb7AEOLAJ/VebhF9kBZObL/ -HYy4Es+bQwKBgHW/4vYuB3IQXNCp/+V+X1BZ+iJOaves3gekekF+b2itFSKFD8JO -9LQhVfKmTheptdmHhgtF0keXxhV8C+vxX1Ndl7EF41FSh5vzmQRAtPHkCvFEviex -TFD70/gSb1lO1UA/Xbqk69yBcprVPAtFejss0EYx2MVj+CLftmIEwW0ZAoGBAIMG -EVQ45eikLXjkn78+Iq7VZbIJX6IdNBH29I+GqsUJJ5Yw6fh6P3KwF3qG+mvmTfYn -sUAFXS+r58rYwVsRVsxlGmKmUc7hmhibhaEVH72QtvWuEiexbRG+viKfIVuA7t39 -3wXpWZiQ4yBdU4Pgt9wrVEU7ukyGaHiReOa7s90jAoGAJc0K7smn98YutQQ+g2ur -ybfnsl0YdsksaP2S2zvZUmNevKPrgnaIDDabOlhYYga+AK1G3FQ7/nefUgiIg1Nd -kr+T6Q4osS3xHB6Az9p/jaF4R2KaWN2nNVCn7ecsmPxDdM7k1vLxaT26vwO9OP5f -YU/5CeIzrfA5nQyPZkOXZBk= ------END PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUF2VIP4+AnEtb52KTCHbo4+fESfswDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTEwMzAyMjQ2MjBaFw0yMjA4 -MTkyMjQ2MjBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDL1hG+JYCfIPp3tlZ05J4pYIJ3Ckfs432bE3rYuWlR -2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRYOCI69s4+lP3DwR8uBCp9xyVkF8th -XfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+QfoxAb6tx0kEc7V3ozBLWoIDJjfwJ3 -NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIrAa7pxHzo/Nd0U3e7z+DlBcJV7dY6 -TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bClG0u7unS7QOBMd6bOGkeL+Bc+n22 -slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpXwj/Ek0F7AgMBAAGjUzBRMB0GA1Ud -DgQWBBT6Mf9uXFB67bY2PeW3GCTKfkO7vDAfBgNVHSMEGDAWgBT6Mf9uXFB67bY2 -PeW3GCTKfkO7vDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCZ -1+kTISX85v9/ag7glavaPFUYsOSOOofl8gSzov7L01YL+srq7tXdvZmWrjQ/dnOY -h18rp9rb24vwIYxNioNG/M2cW1jBJwEGsDPOwdPV1VPcRmmUJW9kY130gRHBCd/N -qB7dIkcQnpNsxPIIWI+sRQp73U0ijhOByDnCNHLHon6vbfFTwkO1XggmV5BdZ3uQ -JNJyckILyNzlhmf6zhonMp4lVzkgxWsAm2vgdawd6dmBa+7Avb2QK9s+IdUSutFh -DgW2L12Obgh12Y4sf1iKQXA0RbZ2k+XQIz8EKZa7vJQY0ciYXSgB/BV3a96xX3cx -LIPL8Vam8Ytkopi3gsGA ------END CERTIFICATE----- \ No newline at end of file diff --git a/sdk/azidentity/testdata/certificate_formatB.pem b/sdk/azidentity/testdata/certificate_formatB.pem deleted file mode 100644 index 3896c163dfed..000000000000 --- a/sdk/azidentity/testdata/certificate_formatB.pem +++ /dev/null @@ -1,49 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUF2VIP4+AnEtb52KTCHbo4+fESfswDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTEwMzAyMjQ2MjBaFw0yMjA4 -MTkyMjQ2MjBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDL1hG+JYCfIPp3tlZ05J4pYIJ3Ckfs432bE3rYuWlR -2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRYOCI69s4+lP3DwR8uBCp9xyVkF8th -XfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+QfoxAb6tx0kEc7V3ozBLWoIDJjfwJ3 -NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIrAa7pxHzo/Nd0U3e7z+DlBcJV7dY6 -TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bClG0u7unS7QOBMd6bOGkeL+Bc+n22 -slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpXwj/Ek0F7AgMBAAGjUzBRMB0GA1Ud -DgQWBBT6Mf9uXFB67bY2PeW3GCTKfkO7vDAfBgNVHSMEGDAWgBT6Mf9uXFB67bY2 -PeW3GCTKfkO7vDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCZ -1+kTISX85v9/ag7glavaPFUYsOSOOofl8gSzov7L01YL+srq7tXdvZmWrjQ/dnOY -h18rp9rb24vwIYxNioNG/M2cW1jBJwEGsDPOwdPV1VPcRmmUJW9kY130gRHBCd/N -qB7dIkcQnpNsxPIIWI+sRQp73U0ijhOByDnCNHLHon6vbfFTwkO1XggmV5BdZ3uQ -JNJyckILyNzlhmf6zhonMp4lVzkgxWsAm2vgdawd6dmBa+7Avb2QK9s+IdUSutFh -DgW2L12Obgh12Y4sf1iKQXA0RbZ2k+XQIz8EKZa7vJQY0ciYXSgB/BV3a96xX3cx -LIPL8Vam8Ytkopi3gsGA ------END CERTIFICATE----- ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDL1hG+JYCfIPp3 -tlZ05J4pYIJ3Ckfs432bE3rYuWlR2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRY -OCI69s4+lP3DwR8uBCp9xyVkF8thXfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+Qf -oxAb6tx0kEc7V3ozBLWoIDJjfwJ3NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIr -Aa7pxHzo/Nd0U3e7z+DlBcJV7dY6TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bC -lG0u7unS7QOBMd6bOGkeL+Bc+n22slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpX -wj/Ek0F7AgMBAAECggEAblU3UWdXUcs2CCqIbcl52wfEVs8X05/n01MeAcWKvqYG -hvGcz7eLvhir5dQoXcF3VhybMrIe6C4WcBIiZSxGwxU+rwEP8YaLwX1UPfOrQM7s -sZTdFTLWfUslO3p7q300fdRA92iG9COMDZvkElh0cBvQksxs9sSr149l9vk+ymtC -uBhZtHG6Ki0BIMBNC9jGUqDuOatXl/dkK4tNjXrNJT7tVwzPaqnNALIWl6B+k9oQ -m1oNhSH2rvs9tw2ITXfIoIk9KdOMjQVUD43wKOaz0hNZhUsb1OFuls7UtRzaFcZH -rMd/M8DtA104QTTlHK+XS7r+nqdv7+ZyB+suTdM+oQKBgQDxCrJZU3hJ0eJ4VYhK -xGDfVGNpYxNkQ4CDB9fwRNbFr/Ck3kgzfE9QxTx1pJOolVmfuFmk9B86in4UNy91 -KdaqT79AU5RdOBXNN6tuMbLC0AVqe8sZq+1vWVVwbCstffxEMmyW1Ju/FLYPl2Zp -e5P96dBh5B3mXrQtpDJ0RkxxaQKBgQDYfE6tQQnQSs2ewD6ae8Mu6j8ueDlVoZ37 -vze1QdBasR26xu2H8XBt3u41zc524BwQsB1GE1tnC8ZylrqwVEayK4FesSQRCO6o -yK8QSdb06I5J4TaN+TppCDPLzstOh0Dmxp+iFUGoErb7AEOLAJ/VebhF9kBZObL/ -HYy4Es+bQwKBgHW/4vYuB3IQXNCp/+V+X1BZ+iJOaves3gekekF+b2itFSKFD8JO -9LQhVfKmTheptdmHhgtF0keXxhV8C+vxX1Ndl7EF41FSh5vzmQRAtPHkCvFEviex -TFD70/gSb1lO1UA/Xbqk69yBcprVPAtFejss0EYx2MVj+CLftmIEwW0ZAoGBAIMG -EVQ45eikLXjkn78+Iq7VZbIJX6IdNBH29I+GqsUJJ5Yw6fh6P3KwF3qG+mvmTfYn -sUAFXS+r58rYwVsRVsxlGmKmUc7hmhibhaEVH72QtvWuEiexbRG+viKfIVuA7t39 -3wXpWZiQ4yBdU4Pgt9wrVEU7ukyGaHiReOa7s90jAoGAJc0K7smn98YutQQ+g2ur -ybfnsl0YdsksaP2S2zvZUmNevKPrgnaIDDabOlhYYga+AK1G3FQ7/nefUgiIg1Nd -kr+T6Q4osS3xHB6Az9p/jaF4R2KaWN2nNVCn7ecsmPxDdM7k1vLxaT26vwO9OP5f -YU/5CeIzrfA5nQyPZkOXZBk= ------END PRIVATE KEY----- \ No newline at end of file diff --git a/sdk/azidentity/testdata/certificate_nokey.pem b/sdk/azidentity/testdata/certificate_nokey.pem deleted file mode 100644 index 465db0813cef..000000000000 --- a/sdk/azidentity/testdata/certificate_nokey.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUF2VIP4+AnEtb52KTCHbo4+fESfswDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xOTEwMzAyMjQ2MjBaFw0yMjA4 -MTkyMjQ2MjBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDL1hG+JYCfIPp3tlZ05J4pYIJ3Ckfs432bE3rYuWlR -2w9KqdjWkKxuAxpjJ+T+uoqVaT3BFMfi4ZRYOCI69s4+lP3DwR8uBCp9xyVkF8th -XfS3iui0liGDviVBoBJJWvjDFU8a/Hseg+QfoxAb6tx0kEc7V3ozBLWoIDJjfwJ3 -NdsLZGVtAC34qCWeEIvS97CDA4g3Kc6hYJIrAa7pxHzo/Nd0U3e7z+DlBcJV7dY6 -TZUyjBVTpzppWe+XQEOfKsjkDNykHEC1C1bClG0u7unS7QOBMd6bOGkeL+Bc+n22 -slTzs5amsbDLNuobSaUsFt9vgD5jRD6FwhpXwj/Ek0F7AgMBAAGjUzBRMB0GA1Ud -DgQWBBT6Mf9uXFB67bY2PeW3GCTKfkO7vDAfBgNVHSMEGDAWgBT6Mf9uXFB67bY2 -PeW3GCTKfkO7vDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCZ -1+kTISX85v9/ag7glavaPFUYsOSOOofl8gSzov7L01YL+srq7tXdvZmWrjQ/dnOY -h18rp9rb24vwIYxNioNG/M2cW1jBJwEGsDPOwdPV1VPcRmmUJW9kY130gRHBCd/N -qB7dIkcQnpNsxPIIWI+sRQp73U0ijhOByDnCNHLHon6vbfFTwkO1XggmV5BdZ3uQ -JNJyckILyNzlhmf6zhonMp4lVzkgxWsAm2vgdawd6dmBa+7Avb2QK9s+IdUSutFh -DgW2L12Obgh12Y4sf1iKQXA0RbZ2k+XQIz8EKZa7vJQY0ciYXSgB/BV3a96xX3cx -LIPL8Vam8Ytkopi3gsGA ------END CERTIFICATE----- \ No newline at end of file diff --git a/sdk/azidentity/username_password_credential.go b/sdk/azidentity/username_password_credential.go deleted file mode 100644 index 155a837644a7..000000000000 --- a/sdk/azidentity/username_password_credential.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -// UsernamePasswordCredential enables authentication to Azure Active Directory using a user's username and password. If the user has MFA enabled this -// credential will fail to get a token returning an AuthenticationFailureError. Also, this credential requires a high degree of trust and is not -// recommended outside of prototyping when more secure credentials can be used. -type UsernamePasswordCredential struct { - azcore.TokenCredential - client *aadIdentityClient - tenantID string // Gets the Azure Active Directory tenant (directory) ID of the service principal - clientID string // Gets the client (application) ID of the service principal - username string // Gets the user account's user name - password string // Gets the user account's password -} - -// NewUsernamePasswordCredential constructs a new UsernamePasswordCredential with the details needed to authenticate against Azure Active Directory with -// a simple username and password. -// tenantID: The Azure Active Directory tenant (directory) ID of the service principal. -// clientID: The client (application) ID of the service principal. -// username: A user's account username -// password: A user's account password -// options: TokenCredentialOptions used to configure the pipeline for the requests sent to Azure Active Directory. -func NewUsernamePasswordCredential(tenantID string, clientID string, username string, password string, options *TokenCredentialOptions) (*UsernamePasswordCredential, error) { - c, err := newAADIdentityClient(options) - if err != nil { - return nil, err - } - return &UsernamePasswordCredential{tenantID: tenantID, clientID: clientID, username: username, password: password, client: c}, nil -} - -// GetToken obtains a token from Azure Active Directory using the specified username and password. -// scopes: The list of scopes for which the token will have access. -// ctx: The context used to control the request lifetime. -// Returns an AccessToken which can be used to authenticate service client calls. -func (c *UsernamePasswordCredential) GetToken(ctx context.Context, opts azcore.TokenRequestOptions) (*azcore.AccessToken, error) { - tk, err := c.client.authenticateUsernamePassword(ctx, c.tenantID, c.clientID, c.username, c.password, opts.Scopes) - if err != nil { - addGetTokenFailureLogs("Username Password Credential", err) - return nil, err - } - azcore.Log().Write(LogCredential, logGetTokenSuccess(c, opts)) - return tk, err -} - -// AuthenticationPolicy implements the azcore.Credential interface on UsernamePasswordCredential. -func (c *UsernamePasswordCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) -} diff --git a/sdk/azidentity/username_password_credential_test.go b/sdk/azidentity/username_password_credential_test.go deleted file mode 100644 index 6fd36e547108..000000000000 --- a/sdk/azidentity/username_password_credential_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "context" - "io/ioutil" - "net/http" - "net/url" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" -) - -func TestUsernamePasswordCredential_CreateAuthRequestSuccess(t *testing.T) { - cred, err := NewUsernamePasswordCredential(tenantID, clientID, "username", "password", nil) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - req, err := cred.client.createUsernamePasswordAuthRequest(cred.tenantID, cred.clientID, cred.username, cred.password, []string{scope}) - if err != nil { - t.Fatalf("Unexpectedly received an error: %v", err) - } - if req.Request.Header.Get(azcore.HeaderContentType) != azcore.HeaderURLEncoded { - t.Fatalf("Unexpected value for Content-Type header") - } - body, err := ioutil.ReadAll(req.Request.Body) - if err != nil { - t.Fatalf("Unable to read request body") - } - bodyStr := string(body) - reqQueryParams, err := url.ParseQuery(bodyStr) - if err != nil { - t.Fatalf("Unable to parse query params in request") - } - if reqQueryParams[qpResponseType][0] != "token" { - t.Fatalf("Unexpected response type") - } - if reqQueryParams[qpGrantType][0] != "password" { - t.Fatalf("Unexpected grant type") - } - if reqQueryParams[qpClientID][0] != clientID { - t.Fatalf("Unexpected client ID in the client_id header") - } - if reqQueryParams[qpUsername][0] != "username" { - t.Fatalf("Unexpected username in the username header") - } - if reqQueryParams[qpPassword][0] != "password" { - t.Fatalf("Unexpected password in the password header") - } - if reqQueryParams[qpScope][0] != scope { - t.Fatalf("Unexpected scope in scope header") - } - if req.Request.URL.Host != defaultTestAuthorityHost { - t.Fatalf("Unexpected default authority host") - } - if req.Request.URL.Scheme != "https" { - t.Fatalf("Wrong request scheme") - } -} - -func TestUsernamePasswordCredential_GetTokenSuccess(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srvURL := srv.URL() - cred, err := NewUsernamePasswordCredential(tenantID, clientID, "username", "password", &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err != nil { - t.Fatalf("Expected an empty error but received: %s", err.Error()) - } -} - -func TestUsernamePasswordCredential_GetTokenInvalidCredentials(t *testing.T) { - srv, close := mock.NewServer() - defer close() - srv.SetResponse(mock.WithStatusCode(http.StatusUnauthorized)) - srvURL := srv.URL() - cred, err := NewUsernamePasswordCredential(tenantID, clientID, "username", "wrong_password", &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - _, err = cred.GetToken(context.Background(), azcore.TokenRequestOptions{Scopes: []string{scope}}) - if err == nil { - t.Fatalf("Expected an error but did not receive one.") - } -} - -func TestBearerPolicy_UsernamePasswordCredential(t *testing.T) { - srv, close := mock.NewTLSServer() - defer close() - srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess))) - srv.AppendResponse(mock.WithStatusCode(http.StatusOK)) - srvURL := srv.URL() - cred, err := NewUsernamePasswordCredential(tenantID, clientID, "username", "password", &TokenCredentialOptions{HTTPClient: srv, AuthorityHost: &srvURL}) - if err != nil { - t.Fatalf("Unable to create credential. Received: %v", err) - } - pipeline := azcore.NewPipeline( - srv, - azcore.NewTelemetryPolicy(azcore.TelemetryOptions{}), - azcore.NewUniqueRequestIDPolicy(), - azcore.NewRetryPolicy(nil), - cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), - azcore.NewRequestLogPolicy(azcore.RequestLogOptions{})) - _, err = pipeline.Do(context.Background(), azcore.NewRequest(http.MethodGet, srv.URL())) - if err != nil { - t.Fatalf("Expected an empty error but receive: %v", err) - } -} diff --git a/sdk/storage/blob/2019-07-07/azblob/appendblob.go b/sdk/storage/blob/2019-07-07/azblob/appendblob.go index f8608989b1f1..92a153cb8437 100644 --- a/sdk/storage/blob/2019-07-07/azblob/appendblob.go +++ b/sdk/storage/blob/2019-07-07/azblob/appendblob.go @@ -18,21 +18,21 @@ import ( // AppendBlobOperations contains the methods for the AppendBlob group. type AppendBlobOperations interface { // 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. - AppendBlock(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, options *AppendBlobAppendBlockOptions) (*AppendBlobAppendBlockResponse, error) + AppendBlock(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, appendBlobAppendBlockOptions *AppendBlobAppendBlockOptions, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*AppendBlobAppendBlockResponse, error) // 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. - AppendBlockFromURL(ctx context.Context, sourceUrl url.URL, contentLength int64, options *AppendBlobAppendBlockFromURLOptions) (*AppendBlobAppendBlockFromURLResponse, error) + AppendBlockFromURL(ctx context.Context, sourceUrl url.URL, contentLength int64, appendBlobAppendBlockFromUrlOptions *AppendBlobAppendBlockFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*AppendBlobAppendBlockFromURLResponse, error) // Create - The Create Append Blob operation creates a new append blob. - Create(ctx context.Context, contentLength int64, options *AppendBlobCreateOptions) (*AppendBlobCreateResponse, error) + Create(ctx context.Context, contentLength int64, appendBlobCreateOptions *AppendBlobCreateOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*AppendBlobCreateResponse, error) } // appendBlobOperations implements the AppendBlobOperations interface. type appendBlobOperations struct { - *Client + *client } // 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. -func (client *appendBlobOperations) AppendBlock(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, options *AppendBlobAppendBlockOptions) (*AppendBlobAppendBlockResponse, error) { - req, err := client.appendBlockCreateRequest(contentLength, body, options) +func (client *appendBlobOperations) AppendBlock(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, appendBlobAppendBlockOptions *AppendBlobAppendBlockOptions, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*AppendBlobAppendBlockResponse, error) { + req, err := client.appendBlockCreateRequest(contentLength, body, appendBlobAppendBlockOptions, leaseAccessConditions, appendPositionAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -48,55 +48,56 @@ func (client *appendBlobOperations) AppendBlock(ctx context.Context, contentLeng } // appendBlockCreateRequest creates the AppendBlock request. -func (client *appendBlobOperations) appendBlockCreateRequest(contentLength int64, body azcore.ReadSeekCloser, options *AppendBlobAppendBlockOptions) (*azcore.Request, error) { - u := client.u +func (client *appendBlobOperations) appendBlockCreateRequest(contentLength int64, body azcore.ReadSeekCloser, appendBlobAppendBlockOptions *AppendBlobAppendBlockOptions, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "appendblock") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if appendBlobAppendBlockOptions != nil && appendBlobAppendBlockOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*appendBlobAppendBlockOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.TransactionalContentMd5 != nil { - req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*options.TransactionalContentMd5)) + if appendBlobAppendBlockOptions != nil && appendBlobAppendBlockOptions.TransactionalContentMd5 != nil { + req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*appendBlobAppendBlockOptions.TransactionalContentMd5)) } - if options != nil && options.TransactionalContentCrc64 != nil { - req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*options.TransactionalContentCrc64)) + if appendBlobAppendBlockOptions != nil && appendBlobAppendBlockOptions.TransactionalContentCrc64 != nil { + req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*appendBlobAppendBlockOptions.TransactionalContentCrc64)) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.MaxSize != nil { - req.Header.Set("x-ms-blob-condition-maxsize", strconv.FormatInt(*options.MaxSize, 10)) + if appendPositionAccessConditions != nil && appendPositionAccessConditions.MaxSize != nil { + req.Header.Set("x-ms-blob-condition-maxsize", strconv.FormatInt(*appendPositionAccessConditions.MaxSize, 10)) } - if options != nil && options.AppendPosition != nil { - req.Header.Set("x-ms-blob-condition-appendpos", strconv.FormatInt(*options.AppendPosition, 10)) + if appendPositionAccessConditions != nil && appendPositionAccessConditions.AppendPosition != nil { + req.Header.Set("x-ms-blob-condition-appendpos", strconv.FormatInt(*appendPositionAccessConditions.AppendPosition, 10)) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if appendBlobAppendBlockOptions != nil && appendBlobAppendBlockOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *appendBlobAppendBlockOptions.RequestId) } return req, req.SetBody(body) } @@ -104,7 +105,7 @@ func (client *appendBlobOperations) appendBlockCreateRequest(contentLength int64 // appendBlockHandleResponse handles the AppendBlock response. func (client *appendBlobOperations) appendBlockHandleResponse(resp *azcore.Response) (*AppendBlobAppendBlockResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.appendBlockHandleError(resp) } result := AppendBlobAppendBlockResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -174,9 +175,18 @@ func (client *appendBlobOperations) appendBlockHandleResponse(resp *azcore.Respo return &result, nil } +// appendBlockHandleError handles the AppendBlock error response. +func (client *appendBlobOperations) appendBlockHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *appendBlobOperations) AppendBlockFromURL(ctx context.Context, sourceUrl url.URL, contentLength int64, options *AppendBlobAppendBlockFromURLOptions) (*AppendBlobAppendBlockFromURLResponse, error) { - req, err := client.appendBlockFromUrlCreateRequest(sourceUrl, contentLength, options) +func (client *appendBlobOperations) AppendBlockFromURL(ctx context.Context, sourceUrl url.URL, contentLength int64, appendBlobAppendBlockFromUrlOptions *AppendBlobAppendBlockFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*AppendBlobAppendBlockFromURLResponse, error) { + req, err := client.appendBlockFromUrlCreateRequest(sourceUrl, contentLength, appendBlobAppendBlockFromUrlOptions, cpkInfo, cpkScopeInfo, leaseAccessConditions, appendPositionAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions) if err != nil { return nil, err } @@ -192,74 +202,75 @@ func (client *appendBlobOperations) AppendBlockFromURL(ctx context.Context, sour } // appendBlockFromUrlCreateRequest creates the AppendBlockFromURL request. -func (client *appendBlobOperations) appendBlockFromUrlCreateRequest(sourceUrl url.URL, contentLength int64, options *AppendBlobAppendBlockFromURLOptions) (*azcore.Request, error) { - u := client.u +func (client *appendBlobOperations) appendBlockFromUrlCreateRequest(sourceUrl url.URL, contentLength int64, appendBlobAppendBlockFromUrlOptions *AppendBlobAppendBlockFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "appendblock") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if appendBlobAppendBlockFromUrlOptions != nil && appendBlobAppendBlockFromUrlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*appendBlobAppendBlockFromUrlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-copy-source", sourceUrl.String()) - if options != nil && options.SourceRange != nil { - req.Header.Set("x-ms-source-range", *options.SourceRange) + if appendBlobAppendBlockFromUrlOptions != nil && appendBlobAppendBlockFromUrlOptions.SourceRange != nil { + req.Header.Set("x-ms-source-range", *appendBlobAppendBlockFromUrlOptions.SourceRange) } - if options != nil && options.SourceContentMd5 != nil { - req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*options.SourceContentMd5)) + if appendBlobAppendBlockFromUrlOptions != nil && appendBlobAppendBlockFromUrlOptions.SourceContentMd5 != nil { + req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*appendBlobAppendBlockFromUrlOptions.SourceContentMd5)) } - if options != nil && options.SourceContentcrc64 != nil { - req.Header.Set("x-ms-source-content-crc64", base64.StdEncoding.EncodeToString(*options.SourceContentcrc64)) + if appendBlobAppendBlockFromUrlOptions != nil && appendBlobAppendBlockFromUrlOptions.SourceContentcrc64 != nil { + req.Header.Set("x-ms-source-content-crc64", base64.StdEncoding.EncodeToString(*appendBlobAppendBlockFromUrlOptions.SourceContentcrc64)) } req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.TransactionalContentMd5 != nil { - req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*options.TransactionalContentMd5)) + if appendBlobAppendBlockFromUrlOptions != nil && appendBlobAppendBlockFromUrlOptions.TransactionalContentMd5 != nil { + req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*appendBlobAppendBlockFromUrlOptions.TransactionalContentMd5)) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.MaxSize != nil { - req.Header.Set("x-ms-blob-condition-maxsize", strconv.FormatInt(*options.MaxSize, 10)) + if appendPositionAccessConditions != nil && appendPositionAccessConditions.MaxSize != nil { + req.Header.Set("x-ms-blob-condition-maxsize", strconv.FormatInt(*appendPositionAccessConditions.MaxSize, 10)) } - if options != nil && options.AppendPosition != nil { - req.Header.Set("x-ms-blob-condition-appendpos", strconv.FormatInt(*options.AppendPosition, 10)) + if appendPositionAccessConditions != nil && appendPositionAccessConditions.AppendPosition != nil { + req.Header.Set("x-ms-blob-condition-appendpos", strconv.FormatInt(*appendPositionAccessConditions.AppendPosition, 10)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.SourceIfModifiedSince != nil { - req.Header.Set("x-ms-source-if-modified-since", options.SourceIfModifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Header.Set("x-ms-source-if-modified-since", sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfUnmodifiedSince != nil { - req.Header.Set("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Header.Set("x-ms-source-if-unmodified-since", sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfMatch != nil { - req.Header.Set("x-ms-source-if-match", *options.SourceIfMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Header.Set("x-ms-source-if-match", *sourceModifiedAccessConditions.SourceIfMatch) } - if options != nil && options.SourceIfNoneMatch != nil { - req.Header.Set("x-ms-source-if-none-match", *options.SourceIfNoneMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Header.Set("x-ms-source-if-none-match", *sourceModifiedAccessConditions.SourceIfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if appendBlobAppendBlockFromUrlOptions != nil && appendBlobAppendBlockFromUrlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *appendBlobAppendBlockFromUrlOptions.RequestId) } return req, nil } @@ -267,7 +278,7 @@ func (client *appendBlobOperations) appendBlockFromUrlCreateRequest(sourceUrl ur // appendBlockFromUrlHandleResponse handles the AppendBlockFromURL response. func (client *appendBlobOperations) appendBlockFromUrlHandleResponse(resp *azcore.Response) (*AppendBlobAppendBlockFromURLResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.appendBlockFromUrlHandleError(resp) } result := AppendBlobAppendBlockFromURLResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -334,9 +345,18 @@ func (client *appendBlobOperations) appendBlockFromUrlHandleResponse(resp *azcor return &result, nil } +// appendBlockFromUrlHandleError handles the AppendBlockFromURL error response. +func (client *appendBlobOperations) appendBlockFromUrlHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Create - The Create Append Blob operation creates a new append blob. -func (client *appendBlobOperations) Create(ctx context.Context, contentLength int64, options *AppendBlobCreateOptions) (*AppendBlobCreateResponse, error) { - req, err := client.createCreateRequest(contentLength, options) +func (client *appendBlobOperations) Create(ctx context.Context, contentLength int64, appendBlobCreateOptions *AppendBlobCreateOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*AppendBlobCreateResponse, error) { + req, err := client.createCreateRequest(contentLength, appendBlobCreateOptions, blobHttpHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -352,64 +372,67 @@ func (client *appendBlobOperations) Create(ctx context.Context, contentLength in } // createCreateRequest creates the Create request. -func (client *appendBlobOperations) createCreateRequest(contentLength int64, options *AppendBlobCreateOptions) (*azcore.Request, error) { - u := client.u +func (client *appendBlobOperations) createCreateRequest(contentLength int64, appendBlobCreateOptions *AppendBlobCreateOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if appendBlobCreateOptions != nil && appendBlobCreateOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*appendBlobCreateOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-blob-type", "AppendBlob") req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.BlobContentType != nil { - req.Header.Set("x-ms-blob-content-type", *options.BlobContentType) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentType != nil { + req.Header.Set("x-ms-blob-content-type", *blobHttpHeaders.BlobContentType) } - if options != nil && options.BlobContentEncoding != nil { - req.Header.Set("x-ms-blob-content-encoding", *options.BlobContentEncoding) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentEncoding != nil { + req.Header.Set("x-ms-blob-content-encoding", *blobHttpHeaders.BlobContentEncoding) } - if options != nil && options.BlobContentLanguage != nil { - req.Header.Set("x-ms-blob-content-language", *options.BlobContentLanguage) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentLanguage != nil { + req.Header.Set("x-ms-blob-content-language", *blobHttpHeaders.BlobContentLanguage) } - if options != nil && options.BlobContentMd5 != nil { - req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*options.BlobContentMd5)) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentMd5 != nil { + req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*blobHttpHeaders.BlobContentMd5)) } - if options != nil && options.BlobCacheControl != nil { - req.Header.Set("x-ms-blob-cache-control", *options.BlobCacheControl) + if blobHttpHeaders != nil && blobHttpHeaders.BlobCacheControl != nil { + req.Header.Set("x-ms-blob-cache-control", *blobHttpHeaders.BlobCacheControl) } - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if appendBlobCreateOptions != nil && appendBlobCreateOptions.Metadata != nil { + for k, v := range *appendBlobCreateOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.BlobContentDisposition != nil { - req.Header.Set("x-ms-blob-content-disposition", *options.BlobContentDisposition) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentDisposition != nil { + req.Header.Set("x-ms-blob-content-disposition", *blobHttpHeaders.BlobContentDisposition) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if appendBlobCreateOptions != nil && appendBlobCreateOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *appendBlobCreateOptions.RequestId) } return req, nil } @@ -417,7 +440,7 @@ func (client *appendBlobOperations) createCreateRequest(contentLength int64, opt // createHandleResponse handles the Create response. func (client *appendBlobOperations) createHandleResponse(resp *azcore.Response) (*AppendBlobCreateResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.createHandleError(resp) } result := AppendBlobCreateResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -468,3 +491,12 @@ func (client *appendBlobOperations) createHandleResponse(resp *azcore.Response) } return &result, nil } + +// createHandleError handles the Create error response. +func (client *appendBlobOperations) createHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} diff --git a/sdk/storage/blob/2019-07-07/azblob/blob.go b/sdk/storage/blob/2019-07-07/azblob/blob.go index fdae37254de4..1a0cc31058b7 100644 --- a/sdk/storage/blob/2019-07-07/azblob/blob.go +++ b/sdk/storage/blob/2019-07-07/azblob/blob.go @@ -18,56 +18,56 @@ import ( // BlobOperations contains the methods for the Blob group. type BlobOperations interface { // 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. - AbortCopyFromURL(ctx context.Context, copyId string, options *BlobAbortCopyFromURLOptions) (*BlobAbortCopyFromURLResponse, error) + AbortCopyFromURL(ctx context.Context, copyId string, blobAbortCopyFromUrlOptions *BlobAbortCopyFromURLOptions, leaseAccessConditions *LeaseAccessConditions) (*BlobAbortCopyFromURLResponse, error) // AcquireLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations - AcquireLease(ctx context.Context, options *BlobAcquireLeaseOptions) (*BlobAcquireLeaseResponse, error) + AcquireLease(ctx context.Context, blobAcquireLeaseOptions *BlobAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobAcquireLeaseResponse, error) // BreakLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations - BreakLease(ctx context.Context, options *BlobBreakLeaseOptions) (*BlobBreakLeaseResponse, error) + BreakLease(ctx context.Context, blobBreakLeaseOptions *BlobBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobBreakLeaseResponse, error) // ChangeLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations - ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, options *BlobChangeLeaseOptions) (*BlobChangeLeaseResponse, error) + ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, blobChangeLeaseOptions *BlobChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobChangeLeaseResponse, error) // 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. - CopyFromURL(ctx context.Context, copySource url.URL, options *BlobCopyFromURLOptions) (*BlobCopyFromURLResponse, error) + CopyFromURL(ctx context.Context, copySource url.URL, blobCopyFromUrlOptions *BlobCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*BlobCopyFromURLResponse, error) // CreateSnapshot - The Create Snapshot operation creates a read-only snapshot of a blob - CreateSnapshot(ctx context.Context, options *BlobCreateSnapshotOptions) (*BlobCreateSnapshotResponse, error) + CreateSnapshot(ctx context.Context, blobCreateSnapshotOptions *BlobCreateSnapshotOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*BlobCreateSnapshotResponse, error) // 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). - Delete(ctx context.Context, options *BlobDeleteOptions) (*BlobDeleteResponse, error) + Delete(ctx context.Context, blobDeleteOptions *BlobDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobDeleteResponse, error) // 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. - Download(ctx context.Context, options *BlobDownloadOptions) (*BlobDownloadResponse, error) + Download(ctx context.Context, blobDownloadOptions *BlobDownloadOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlobDownloadResponse, error) // GetAccessControl - Get the owner, group, permissions, or access control list for a blob. - GetAccessControl(ctx context.Context, options *BlobGetAccessControlOptions) (*BlobGetAccessControlResponse, error) + GetAccessControl(ctx context.Context, blobGetAccessControlOptions *BlobGetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobGetAccessControlResponse, error) // GetAccountInfo - Returns the sku name and account kind GetAccountInfo(ctx context.Context) (*BlobGetAccountInfoResponse, error) // 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. - GetProperties(ctx context.Context, options *BlobGetPropertiesOptions) (*BlobGetPropertiesResponse, error) + GetProperties(ctx context.Context, blobGetPropertiesOptions *BlobGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlobGetPropertiesResponse, error) // ReleaseLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations - ReleaseLease(ctx context.Context, leaseId string, options *BlobReleaseLeaseOptions) (*BlobReleaseLeaseResponse, error) + ReleaseLease(ctx context.Context, leaseId string, blobReleaseLeaseOptions *BlobReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobReleaseLeaseResponse, error) // Rename - Rename a blob/file. 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: "*". - Rename(ctx context.Context, renameSource string, options *BlobRenameOptions) (*BlobRenameResponse, error) + Rename(ctx context.Context, renameSource string, blobRenameOptions *BlobRenameOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*BlobRenameResponse, error) // RenewLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations - RenewLease(ctx context.Context, leaseId string, options *BlobRenewLeaseOptions) (*BlobRenewLeaseResponse, error) + RenewLease(ctx context.Context, leaseId string, blobRenewLeaseOptions *BlobRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobRenewLeaseResponse, error) // SetAccessControl - Set the owner, group, permissions, or access control list for a blob. - SetAccessControl(ctx context.Context, options *BlobSetAccessControlOptions) (*BlobSetAccessControlResponse, error) + SetAccessControl(ctx context.Context, blobSetAccessControlOptions *BlobSetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobSetAccessControlResponse, error) // SetHTTPHeaders - The Set HTTP Headers operation sets system properties on the blob - SetHTTPHeaders(ctx context.Context, options *BlobSetHTTPHeadersOptions) (*BlobSetHTTPHeadersResponse, error) + SetHTTPHeaders(ctx context.Context, blobSetHttpHeadersOptions *BlobSetHTTPHeadersOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobSetHTTPHeadersResponse, error) // SetMetadata - The Set Blob Metadata operation sets user-defined metadata for the specified blob as one or more name-value pairs - SetMetadata(ctx context.Context, options *BlobSetMetadataOptions) (*BlobSetMetadataResponse, error) + SetMetadata(ctx context.Context, blobSetMetadataOptions *BlobSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlobSetMetadataResponse, error) // 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. - SetTier(ctx context.Context, tier AccessTier, options *BlobSetTierOptions) (*BlobSetTierResponse, error) + SetTier(ctx context.Context, tier AccessTier, blobSetTierOptions *BlobSetTierOptions, leaseAccessConditions *LeaseAccessConditions) (*BlobSetTierResponse, error) // StartCopyFromURL - The Start Copy From URL operation copies a blob or an internet resource to a new blob. - StartCopyFromURL(ctx context.Context, copySource url.URL, options *BlobStartCopyFromURLOptions) (*BlobStartCopyFromURLResponse, error) + StartCopyFromURL(ctx context.Context, copySource url.URL, blobStartCopyFromUrlOptions *BlobStartCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*BlobStartCopyFromURLResponse, error) // Undelete - Undelete a blob that was previously soft deleted - Undelete(ctx context.Context, options *BlobUndeleteOptions) (*BlobUndeleteResponse, error) + Undelete(ctx context.Context, blobUndeleteOptions *BlobUndeleteOptions) (*BlobUndeleteResponse, error) } // blobOperations implements the BlobOperations interface. type blobOperations struct { - *Client + *client pathRenameMode *PathRenameMode } // 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. -func (client *blobOperations) AbortCopyFromURL(ctx context.Context, copyId string, options *BlobAbortCopyFromURLOptions) (*BlobAbortCopyFromURLResponse, error) { - req, err := client.abortCopyFromUrlCreateRequest(copyId, options) +func (client *blobOperations) AbortCopyFromURL(ctx context.Context, copyId string, blobAbortCopyFromUrlOptions *BlobAbortCopyFromURLOptions, leaseAccessConditions *LeaseAccessConditions) (*BlobAbortCopyFromURLResponse, error) { + req, err := client.abortCopyFromUrlCreateRequest(copyId, blobAbortCopyFromUrlOptions, leaseAccessConditions) if err != nil { return nil, err } @@ -83,23 +83,24 @@ func (client *blobOperations) AbortCopyFromURL(ctx context.Context, copyId strin } // abortCopyFromUrlCreateRequest creates the AbortCopyFromURL request. -func (client *blobOperations) abortCopyFromUrlCreateRequest(copyId string, options *BlobAbortCopyFromURLOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) abortCopyFromUrlCreateRequest(copyId string, blobAbortCopyFromUrlOptions *BlobAbortCopyFromURLOptions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "copy") query.Set("copyid", copyId) - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobAbortCopyFromUrlOptions != nil && blobAbortCopyFromUrlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobAbortCopyFromUrlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-copy-action", "abort") - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobAbortCopyFromUrlOptions != nil && blobAbortCopyFromUrlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobAbortCopyFromUrlOptions.RequestId) } return req, nil } @@ -107,7 +108,7 @@ func (client *blobOperations) abortCopyFromUrlCreateRequest(copyId string, optio // abortCopyFromUrlHandleResponse handles the AbortCopyFromURL response. func (client *blobOperations) abortCopyFromUrlHandleResponse(resp *azcore.Response) (*BlobAbortCopyFromURLResponse, error) { if !resp.HasStatusCode(http.StatusNoContent) { - return nil, newStorageError(resp) + return nil, client.abortCopyFromUrlHandleError(resp) } result := BlobAbortCopyFromURLResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -129,9 +130,18 @@ func (client *blobOperations) abortCopyFromUrlHandleResponse(resp *azcore.Respon return &result, nil } +// abortCopyFromUrlHandleError handles the AbortCopyFromURL error response. +func (client *blobOperations) abortCopyFromUrlHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // AcquireLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations -func (client *blobOperations) AcquireLease(ctx context.Context, options *BlobAcquireLeaseOptions) (*BlobAcquireLeaseResponse, error) { - req, err := client.acquireLeaseCreateRequest(options) +func (client *blobOperations) AcquireLease(ctx context.Context, blobAcquireLeaseOptions *BlobAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobAcquireLeaseResponse, error) { + req, err := client.acquireLeaseCreateRequest(blobAcquireLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -147,37 +157,38 @@ func (client *blobOperations) AcquireLease(ctx context.Context, options *BlobAcq } // acquireLeaseCreateRequest creates the AcquireLease request. -func (client *blobOperations) acquireLeaseCreateRequest(options *BlobAcquireLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) acquireLeaseCreateRequest(blobAcquireLeaseOptions *BlobAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobAcquireLeaseOptions != nil && blobAcquireLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobAcquireLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "acquire") - if options != nil && options.Duration != nil { - req.Header.Set("x-ms-lease-duration", strconv.FormatInt(int64(*options.Duration), 10)) + if blobAcquireLeaseOptions != nil && blobAcquireLeaseOptions.Duration != nil { + req.Header.Set("x-ms-lease-duration", strconv.FormatInt(int64(*blobAcquireLeaseOptions.Duration), 10)) } - if options != nil && options.ProposedLeaseId != nil { - req.Header.Set("x-ms-proposed-lease-id", *options.ProposedLeaseId) + if blobAcquireLeaseOptions != nil && blobAcquireLeaseOptions.ProposedLeaseId != nil { + req.Header.Set("x-ms-proposed-lease-id", *blobAcquireLeaseOptions.ProposedLeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobAcquireLeaseOptions != nil && blobAcquireLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobAcquireLeaseOptions.RequestId) } return req, nil } @@ -185,7 +196,7 @@ func (client *blobOperations) acquireLeaseCreateRequest(options *BlobAcquireLeas // acquireLeaseHandleResponse handles the AcquireLease response. func (client *blobOperations) acquireLeaseHandleResponse(resp *azcore.Response) (*BlobAcquireLeaseResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.acquireLeaseHandleError(resp) } result := BlobAcquireLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -220,9 +231,18 @@ func (client *blobOperations) acquireLeaseHandleResponse(resp *azcore.Response) return &result, nil } +// acquireLeaseHandleError handles the AcquireLease error response. +func (client *blobOperations) acquireLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // BreakLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations -func (client *blobOperations) BreakLease(ctx context.Context, options *BlobBreakLeaseOptions) (*BlobBreakLeaseResponse, error) { - req, err := client.breakLeaseCreateRequest(options) +func (client *blobOperations) BreakLease(ctx context.Context, blobBreakLeaseOptions *BlobBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobBreakLeaseResponse, error) { + req, err := client.breakLeaseCreateRequest(blobBreakLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -238,34 +258,35 @@ func (client *blobOperations) BreakLease(ctx context.Context, options *BlobBreak } // breakLeaseCreateRequest creates the BreakLease request. -func (client *blobOperations) breakLeaseCreateRequest(options *BlobBreakLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) breakLeaseCreateRequest(blobBreakLeaseOptions *BlobBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobBreakLeaseOptions != nil && blobBreakLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobBreakLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "break") - if options != nil && options.BreakPeriod != nil { - req.Header.Set("x-ms-lease-break-period", strconv.FormatInt(int64(*options.BreakPeriod), 10)) + if blobBreakLeaseOptions != nil && blobBreakLeaseOptions.BreakPeriod != nil { + req.Header.Set("x-ms-lease-break-period", strconv.FormatInt(int64(*blobBreakLeaseOptions.BreakPeriod), 10)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobBreakLeaseOptions != nil && blobBreakLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobBreakLeaseOptions.RequestId) } return req, nil } @@ -273,7 +294,7 @@ func (client *blobOperations) breakLeaseCreateRequest(options *BlobBreakLeaseOpt // breakLeaseHandleResponse handles the BreakLease response. func (client *blobOperations) breakLeaseHandleResponse(resp *azcore.Response) (*BlobBreakLeaseResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.breakLeaseHandleError(resp) } result := BlobBreakLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -313,9 +334,18 @@ func (client *blobOperations) breakLeaseHandleResponse(resp *azcore.Response) (* return &result, nil } +// breakLeaseHandleError handles the BreakLease error response. +func (client *blobOperations) breakLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // ChangeLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations -func (client *blobOperations) ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, options *BlobChangeLeaseOptions) (*BlobChangeLeaseResponse, error) { - req, err := client.changeLeaseCreateRequest(leaseId, proposedLeaseId, options) +func (client *blobOperations) ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, blobChangeLeaseOptions *BlobChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobChangeLeaseResponse, error) { + req, err := client.changeLeaseCreateRequest(leaseId, proposedLeaseId, blobChangeLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -331,33 +361,34 @@ func (client *blobOperations) ChangeLease(ctx context.Context, leaseId string, p } // changeLeaseCreateRequest creates the ChangeLease request. -func (client *blobOperations) changeLeaseCreateRequest(leaseId string, proposedLeaseId string, options *BlobChangeLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) changeLeaseCreateRequest(leaseId string, proposedLeaseId string, blobChangeLeaseOptions *BlobChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobChangeLeaseOptions != nil && blobChangeLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobChangeLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "change") req.Header.Set("x-ms-lease-id", leaseId) req.Header.Set("x-ms-proposed-lease-id", proposedLeaseId) - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobChangeLeaseOptions != nil && blobChangeLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobChangeLeaseOptions.RequestId) } return req, nil } @@ -365,7 +396,7 @@ func (client *blobOperations) changeLeaseCreateRequest(leaseId string, proposedL // changeLeaseHandleResponse handles the ChangeLease response. func (client *blobOperations) changeLeaseHandleResponse(resp *azcore.Response) (*BlobChangeLeaseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.changeLeaseHandleError(resp) } result := BlobChangeLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -400,9 +431,18 @@ func (client *blobOperations) changeLeaseHandleResponse(resp *azcore.Response) ( return &result, nil } +// changeLeaseHandleError handles the ChangeLease error response. +func (client *blobOperations) changeLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *blobOperations) CopyFromURL(ctx context.Context, copySource url.URL, options *BlobCopyFromURLOptions) (*BlobCopyFromURLResponse, error) { - req, err := client.copyFromUrlCreateRequest(copySource, options) +func (client *blobOperations) CopyFromURL(ctx context.Context, copySource url.URL, blobCopyFromUrlOptions *BlobCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*BlobCopyFromURLResponse, error) { + req, err := client.copyFromUrlCreateRequest(copySource, blobCopyFromUrlOptions, sourceModifiedAccessConditions, modifiedAccessConditions, leaseAccessConditions) if err != nil { return nil, err } @@ -418,55 +458,58 @@ func (client *blobOperations) CopyFromURL(ctx context.Context, copySource url.UR } // copyFromUrlCreateRequest creates the CopyFromURL request. -func (client *blobOperations) copyFromUrlCreateRequest(copySource url.URL, options *BlobCopyFromURLOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) copyFromUrlCreateRequest(copySource url.URL, blobCopyFromUrlOptions *BlobCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobCopyFromUrlOptions != nil && blobCopyFromUrlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobCopyFromUrlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-requires-sync", "true") - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if blobCopyFromUrlOptions != nil && blobCopyFromUrlOptions.Metadata != nil { + for k, v := range *blobCopyFromUrlOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.Tier != nil { - req.Header.Set("x-ms-access-tier", string(*options.Tier)) + if blobCopyFromUrlOptions != nil && blobCopyFromUrlOptions.Tier != nil { + req.Header.Set("x-ms-access-tier", string(*blobCopyFromUrlOptions.Tier)) } - if options != nil && options.SourceIfModifiedSince != nil { - req.Header.Set("x-ms-source-if-modified-since", options.SourceIfModifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Header.Set("x-ms-source-if-modified-since", sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfUnmodifiedSince != nil { - req.Header.Set("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Header.Set("x-ms-source-if-unmodified-since", sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfMatch != nil { - req.Header.Set("x-ms-source-if-match", *options.SourceIfMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Header.Set("x-ms-source-if-match", *sourceModifiedAccessConditions.SourceIfMatch) } - if options != nil && options.SourceIfNoneMatch != nil { - req.Header.Set("x-ms-source-if-none-match", *options.SourceIfNoneMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Header.Set("x-ms-source-if-none-match", *sourceModifiedAccessConditions.SourceIfNoneMatch) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-copy-source", copySource.String()) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobCopyFromUrlOptions != nil && blobCopyFromUrlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobCopyFromUrlOptions.RequestId) } - if options != nil && options.SourceContentMd5 != nil { - req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*options.SourceContentMd5)) + if blobCopyFromUrlOptions != nil && blobCopyFromUrlOptions.SourceContentMd5 != nil { + req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*blobCopyFromUrlOptions.SourceContentMd5)) } return req, nil } @@ -474,7 +517,7 @@ func (client *blobOperations) copyFromUrlCreateRequest(copySource url.URL, optio // copyFromUrlHandleResponse handles the CopyFromURL response. func (client *blobOperations) copyFromUrlHandleResponse(resp *azcore.Response) (*BlobCopyFromURLResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.copyFromUrlHandleError(resp) } result := BlobCopyFromURLResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -526,9 +569,18 @@ func (client *blobOperations) copyFromUrlHandleResponse(resp *azcore.Response) ( return &result, nil } +// copyFromUrlHandleError handles the CopyFromURL error response. +func (client *blobOperations) copyFromUrlHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // CreateSnapshot - The Create Snapshot operation creates a read-only snapshot of a blob -func (client *blobOperations) CreateSnapshot(ctx context.Context, options *BlobCreateSnapshotOptions) (*BlobCreateSnapshotResponse, error) { - req, err := client.createSnapshotCreateRequest(options) +func (client *blobOperations) CreateSnapshot(ctx context.Context, blobCreateSnapshotOptions *BlobCreateSnapshotOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*BlobCreateSnapshotResponse, error) { + req, err := client.createSnapshotCreateRequest(blobCreateSnapshotOptions, cpkInfo, cpkScopeInfo, modifiedAccessConditions, leaseAccessConditions) if err != nil { return nil, err } @@ -544,45 +596,48 @@ func (client *blobOperations) CreateSnapshot(ctx context.Context, options *BlobC } // createSnapshotCreateRequest creates the CreateSnapshot request. -func (client *blobOperations) createSnapshotCreateRequest(options *BlobCreateSnapshotOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) createSnapshotCreateRequest(blobCreateSnapshotOptions *BlobCreateSnapshotOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "snapshot") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobCreateSnapshotOptions != nil && blobCreateSnapshotOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobCreateSnapshotOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if blobCreateSnapshotOptions != nil && blobCreateSnapshotOptions.Metadata != nil { + for k, v := range *blobCreateSnapshotOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobCreateSnapshotOptions != nil && blobCreateSnapshotOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobCreateSnapshotOptions.RequestId) } return req, nil } @@ -590,7 +645,7 @@ func (client *blobOperations) createSnapshotCreateRequest(options *BlobCreateSna // createSnapshotHandleResponse handles the CreateSnapshot response. func (client *blobOperations) createSnapshotHandleResponse(resp *azcore.Response) (*BlobCreateSnapshotResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.createSnapshotHandleError(resp) } result := BlobCreateSnapshotResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-snapshot"); val != "" { @@ -632,9 +687,18 @@ func (client *blobOperations) createSnapshotHandleResponse(resp *azcore.Response return &result, nil } +// createSnapshotHandleError handles the CreateSnapshot error response. +func (client *blobOperations) createSnapshotHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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). -func (client *blobOperations) Delete(ctx context.Context, options *BlobDeleteOptions) (*BlobDeleteResponse, error) { - req, err := client.deleteCreateRequest(options) +func (client *blobOperations) Delete(ctx context.Context, blobDeleteOptions *BlobDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobDeleteResponse, error) { + req, err := client.deleteCreateRequest(blobDeleteOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -650,38 +714,39 @@ func (client *blobOperations) Delete(ctx context.Context, options *BlobDeleteOpt } // deleteCreateRequest creates the Delete request. -func (client *blobOperations) deleteCreateRequest(options *BlobDeleteOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) deleteCreateRequest(blobDeleteOptions *BlobDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Snapshot != nil { - query.Set("snapshot", *options.Snapshot) + if blobDeleteOptions != nil && blobDeleteOptions.Snapshot != nil { + query.Set("snapshot", *blobDeleteOptions.Snapshot) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobDeleteOptions != nil && blobDeleteOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobDeleteOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodDelete, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.DeleteSnapshots != nil { - req.Header.Set("x-ms-delete-snapshots", string(*options.DeleteSnapshots)) + if blobDeleteOptions != nil && blobDeleteOptions.DeleteSnapshots != nil { + req.Header.Set("x-ms-delete-snapshots", string(*blobDeleteOptions.DeleteSnapshots)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobDeleteOptions != nil && blobDeleteOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobDeleteOptions.RequestId) } return req, nil } @@ -689,7 +754,7 @@ func (client *blobOperations) deleteCreateRequest(options *BlobDeleteOptions) (* // deleteHandleResponse handles the Delete response. func (client *blobOperations) deleteHandleResponse(resp *azcore.Response) (*BlobDeleteResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.deleteHandleError(resp) } result := BlobDeleteResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -711,9 +776,18 @@ func (client *blobOperations) deleteHandleResponse(resp *azcore.Response) (*Blob return &result, nil } +// deleteHandleError handles the Delete error response. +func (client *blobOperations) deleteHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *blobOperations) Download(ctx context.Context, options *BlobDownloadOptions) (*BlobDownloadResponse, error) { - req, err := client.downloadCreateRequest(options) +func (client *blobOperations) Download(ctx context.Context, blobDownloadOptions *BlobDownloadOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlobDownloadResponse, error) { + req, err := client.downloadCreateRequest(blobDownloadOptions, leaseAccessConditions, cpkInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -729,59 +803,60 @@ func (client *blobOperations) Download(ctx context.Context, options *BlobDownloa } // downloadCreateRequest creates the Download request. -func (client *blobOperations) downloadCreateRequest(options *BlobDownloadOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) downloadCreateRequest(blobDownloadOptions *BlobDownloadOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Snapshot != nil { - query.Set("snapshot", *options.Snapshot) + if blobDownloadOptions != nil && blobDownloadOptions.Snapshot != nil { + query.Set("snapshot", *blobDownloadOptions.Snapshot) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobDownloadOptions != nil && blobDownloadOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobDownloadOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) req.SkipBodyDownload() - if options != nil && options.RangeParameter != nil { - req.Header.Set("x-ms-range", *options.RangeParameter) + if blobDownloadOptions != nil && blobDownloadOptions.RangeParameter != nil { + req.Header.Set("x-ms-range", *blobDownloadOptions.RangeParameter) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.RangeGetContentMd5 != nil { - req.Header.Set("x-ms-range-get-content-md5", strconv.FormatBool(*options.RangeGetContentMd5)) + if blobDownloadOptions != nil && blobDownloadOptions.RangeGetContentMd5 != nil { + req.Header.Set("x-ms-range-get-content-md5", strconv.FormatBool(*blobDownloadOptions.RangeGetContentMd5)) } - if options != nil && options.RangeGetContentCrc64 != nil { - req.Header.Set("x-ms-range-get-content-crc64", strconv.FormatBool(*options.RangeGetContentCrc64)) + if blobDownloadOptions != nil && blobDownloadOptions.RangeGetContentCrc64 != nil { + req.Header.Set("x-ms-range-get-content-crc64", strconv.FormatBool(*blobDownloadOptions.RangeGetContentCrc64)) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobDownloadOptions != nil && blobDownloadOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobDownloadOptions.RequestId) } return req, nil } // downloadHandleResponse handles the Download response. func (client *blobOperations) downloadHandleResponse(resp *azcore.Response) (*BlobDownloadResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + if !resp.HasStatusCode(http.StatusOK, http.StatusPartialContent) { + return nil, client.downloadHandleError(resp) } result := BlobDownloadResponse{RawResponse: resp.Response} if val := resp.Header.Get("Last-Modified"); val != "" { @@ -927,9 +1002,18 @@ func (client *blobOperations) downloadHandleResponse(resp *azcore.Response) (*Bl return &result, nil } +// downloadHandleError handles the Download error response. +func (client *blobOperations) downloadHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetAccessControl - Get the owner, group, permissions, or access control list for a blob. -func (client *blobOperations) GetAccessControl(ctx context.Context, options *BlobGetAccessControlOptions) (*BlobGetAccessControlResponse, error) { - req, err := client.getAccessControlCreateRequest(options) +func (client *blobOperations) GetAccessControl(ctx context.Context, blobGetAccessControlOptions *BlobGetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobGetAccessControlResponse, error) { + req, err := client.getAccessControlCreateRequest(blobGetAccessControlOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -945,35 +1029,36 @@ func (client *blobOperations) GetAccessControl(ctx context.Context, options *Blo } // getAccessControlCreateRequest creates the GetAccessControl request. -func (client *blobOperations) getAccessControlCreateRequest(options *BlobGetAccessControlOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) getAccessControlCreateRequest(blobGetAccessControlOptions *BlobGetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("action", "getAccessControl") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobGetAccessControlOptions != nil && blobGetAccessControlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobGetAccessControlOptions.Timeout), 10)) } - if options != nil && options.Upn != nil { - query.Set("upn", strconv.FormatBool(*options.Upn)) + if blobGetAccessControlOptions != nil && blobGetAccessControlOptions.Upn != nil { + query.Set("upn", strconv.FormatBool(*blobGetAccessControlOptions.Upn)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodHead, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobGetAccessControlOptions != nil && blobGetAccessControlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobGetAccessControlOptions.RequestId) } req.Header.Set("x-ms-version", "2019-07-07") return req, nil @@ -982,7 +1067,7 @@ func (client *blobOperations) getAccessControlCreateRequest(options *BlobGetAcce // getAccessControlHandleResponse handles the GetAccessControl response. func (client *blobOperations) getAccessControlHandleResponse(resp *azcore.Response) (*BlobGetAccessControlResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newDataLakeStorageError(resp) + return nil, client.getAccessControlHandleError(resp) } result := BlobGetAccessControlResponse{RawResponse: resp.Response} if val := resp.Header.Get("Date"); val != "" { @@ -1023,6 +1108,15 @@ func (client *blobOperations) getAccessControlHandleResponse(resp *azcore.Respon return &result, nil } +// getAccessControlHandleError handles the GetAccessControl error response. +func (client *blobOperations) getAccessControlHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetAccountInfo - Returns the sku name and account kind func (client *blobOperations) GetAccountInfo(ctx context.Context) (*BlobGetAccountInfoResponse, error) { req, err := client.getAccountInfoCreateRequest() @@ -1042,7 +1136,8 @@ func (client *blobOperations) GetAccountInfo(ctx context.Context) (*BlobGetAccou // getAccountInfoCreateRequest creates the GetAccountInfo request. func (client *blobOperations) getAccountInfoCreateRequest() (*azcore.Request, error) { - u := client.u + copy := *client.u + u := © query := u.Query() query.Set("restype", "account") query.Set("comp", "properties") @@ -1055,7 +1150,7 @@ func (client *blobOperations) getAccountInfoCreateRequest() (*azcore.Request, er // getAccountInfoHandleResponse handles the GetAccountInfo response. func (client *blobOperations) getAccountInfoHandleResponse(resp *azcore.Response) (*BlobGetAccountInfoResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getAccountInfoHandleError(resp) } result := BlobGetAccountInfoResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -1083,9 +1178,18 @@ func (client *blobOperations) getAccountInfoHandleResponse(resp *azcore.Response return &result, nil } +// getAccountInfoHandleError handles the GetAccountInfo error response. +func (client *blobOperations) getAccountInfoHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *blobOperations) GetProperties(ctx context.Context, options *BlobGetPropertiesOptions) (*BlobGetPropertiesResponse, error) { - req, err := client.getPropertiesCreateRequest(options) +func (client *blobOperations) GetProperties(ctx context.Context, blobGetPropertiesOptions *BlobGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlobGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(blobGetPropertiesOptions, leaseAccessConditions, cpkInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -1101,41 +1205,42 @@ func (client *blobOperations) GetProperties(ctx context.Context, options *BlobGe } // getPropertiesCreateRequest creates the GetProperties request. -func (client *blobOperations) getPropertiesCreateRequest(options *BlobGetPropertiesOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) getPropertiesCreateRequest(blobGetPropertiesOptions *BlobGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Snapshot != nil { - query.Set("snapshot", *options.Snapshot) + if blobGetPropertiesOptions != nil && blobGetPropertiesOptions.Snapshot != nil { + query.Set("snapshot", *blobGetPropertiesOptions.Snapshot) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobGetPropertiesOptions != nil && blobGetPropertiesOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobGetPropertiesOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodHead, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobGetPropertiesOptions != nil && blobGetPropertiesOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobGetPropertiesOptions.RequestId) } return req, nil } @@ -1143,7 +1248,7 @@ func (client *blobOperations) getPropertiesCreateRequest(options *BlobGetPropert // getPropertiesHandleResponse handles the GetProperties response. func (client *blobOperations) getPropertiesHandleResponse(resp *azcore.Response) (*BlobGetPropertiesResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getPropertiesHandleError(resp) } result := BlobGetPropertiesResponse{RawResponse: resp.Response} if val := resp.Header.Get("Last-Modified"); val != "" { @@ -1309,9 +1414,18 @@ func (client *blobOperations) getPropertiesHandleResponse(resp *azcore.Response) return &result, nil } +// getPropertiesHandleError handles the GetProperties error response. +func (client *blobOperations) getPropertiesHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // ReleaseLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations -func (client *blobOperations) ReleaseLease(ctx context.Context, leaseId string, options *BlobReleaseLeaseOptions) (*BlobReleaseLeaseResponse, error) { - req, err := client.releaseLeaseCreateRequest(leaseId, options) +func (client *blobOperations) ReleaseLease(ctx context.Context, leaseId string, blobReleaseLeaseOptions *BlobReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobReleaseLeaseResponse, error) { + req, err := client.releaseLeaseCreateRequest(leaseId, blobReleaseLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -1327,32 +1441,33 @@ func (client *blobOperations) ReleaseLease(ctx context.Context, leaseId string, } // releaseLeaseCreateRequest creates the ReleaseLease request. -func (client *blobOperations) releaseLeaseCreateRequest(leaseId string, options *BlobReleaseLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) releaseLeaseCreateRequest(leaseId string, blobReleaseLeaseOptions *BlobReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobReleaseLeaseOptions != nil && blobReleaseLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobReleaseLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "release") req.Header.Set("x-ms-lease-id", leaseId) - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobReleaseLeaseOptions != nil && blobReleaseLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobReleaseLeaseOptions.RequestId) } return req, nil } @@ -1360,7 +1475,7 @@ func (client *blobOperations) releaseLeaseCreateRequest(leaseId string, options // releaseLeaseHandleResponse handles the ReleaseLease response. func (client *blobOperations) releaseLeaseHandleResponse(resp *azcore.Response) (*BlobReleaseLeaseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.releaseLeaseHandleError(resp) } result := BlobReleaseLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1392,9 +1507,18 @@ func (client *blobOperations) releaseLeaseHandleResponse(resp *azcore.Response) return &result, nil } +// releaseLeaseHandleError handles the ReleaseLease error response. +func (client *blobOperations) releaseLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Rename - Rename a blob/file. 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: "*". -func (client *blobOperations) Rename(ctx context.Context, renameSource string, options *BlobRenameOptions) (*BlobRenameResponse, error) { - req, err := client.renameCreateRequest(renameSource, options) +func (client *blobOperations) Rename(ctx context.Context, renameSource string, blobRenameOptions *BlobRenameOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*BlobRenameResponse, error) { + req, err := client.renameCreateRequest(renameSource, blobRenameOptions, directoryHttpHeaders, leaseAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions) if err != nil { return nil, err } @@ -1410,11 +1534,12 @@ func (client *blobOperations) Rename(ctx context.Context, renameSource string, o } // renameCreateRequest creates the Rename request. -func (client *blobOperations) renameCreateRequest(renameSource string, options *BlobRenameOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) renameCreateRequest(renameSource string, blobRenameOptions *BlobRenameOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobRenameOptions != nil && blobRenameOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobRenameOptions.Timeout), 10)) } if client.pathRenameMode != nil { query.Set("mode", string(*client.pathRenameMode)) @@ -1422,63 +1547,63 @@ func (client *blobOperations) renameCreateRequest(renameSource string, options * u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-rename-source", renameSource) - if options != nil && options.DirectoryProperties != nil { - req.Header.Set("x-ms-properties", *options.DirectoryProperties) + if blobRenameOptions != nil && blobRenameOptions.DirectoryProperties != nil { + req.Header.Set("x-ms-properties", *blobRenameOptions.DirectoryProperties) } - if options != nil && options.PosixPermissions != nil { - req.Header.Set("x-ms-permissions", *options.PosixPermissions) + if blobRenameOptions != nil && blobRenameOptions.PosixPermissions != nil { + req.Header.Set("x-ms-permissions", *blobRenameOptions.PosixPermissions) } - if options != nil && options.PosixUmask != nil { - req.Header.Set("x-ms-umask", *options.PosixUmask) + if blobRenameOptions != nil && blobRenameOptions.PosixUmask != nil { + req.Header.Set("x-ms-umask", *blobRenameOptions.PosixUmask) } - if options != nil && options.CacheControl != nil { - req.Header.Set("x-ms-cache-control", *options.CacheControl) + if directoryHttpHeaders != nil && directoryHttpHeaders.CacheControl != nil { + req.Header.Set("x-ms-cache-control", *directoryHttpHeaders.CacheControl) } - if options != nil && options.ContentType != nil { - req.Header.Set("x-ms-content-type", *options.ContentType) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentType != nil { + req.Header.Set("x-ms-content-type", *directoryHttpHeaders.ContentType) } - if options != nil && options.ContentEncoding != nil { - req.Header.Set("x-ms-content-encoding", *options.ContentEncoding) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentEncoding != nil { + req.Header.Set("x-ms-content-encoding", *directoryHttpHeaders.ContentEncoding) } - if options != nil && options.ContentLanguage != nil { - req.Header.Set("x-ms-content-language", *options.ContentLanguage) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentLanguage != nil { + req.Header.Set("x-ms-content-language", *directoryHttpHeaders.ContentLanguage) } - if options != nil && options.ContentDisposition != nil { - req.Header.Set("x-ms-content-disposition", *options.ContentDisposition) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentDisposition != nil { + req.Header.Set("x-ms-content-disposition", *directoryHttpHeaders.ContentDisposition) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.SourceLeaseId != nil { - req.Header.Set("x-ms-source-lease-id", *options.SourceLeaseId) + if blobRenameOptions != nil && blobRenameOptions.SourceLeaseId != nil { + req.Header.Set("x-ms-source-lease-id", *blobRenameOptions.SourceLeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.SourceIfModifiedSince != nil { - req.Header.Set("x-ms-source-if-modified-since", options.SourceIfModifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Header.Set("x-ms-source-if-modified-since", sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfUnmodifiedSince != nil { - req.Header.Set("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Header.Set("x-ms-source-if-unmodified-since", sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfMatch != nil { - req.Header.Set("x-ms-source-if-match", *options.SourceIfMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Header.Set("x-ms-source-if-match", *sourceModifiedAccessConditions.SourceIfMatch) } - if options != nil && options.SourceIfNoneMatch != nil { - req.Header.Set("x-ms-source-if-none-match", *options.SourceIfNoneMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Header.Set("x-ms-source-if-none-match", *sourceModifiedAccessConditions.SourceIfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobRenameOptions != nil && blobRenameOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobRenameOptions.RequestId) } return req, nil } @@ -1486,7 +1611,7 @@ func (client *blobOperations) renameCreateRequest(renameSource string, options * // renameHandleResponse handles the Rename response. func (client *blobOperations) renameHandleResponse(resp *azcore.Response) (*BlobRenameResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newDataLakeStorageError(resp) + return nil, client.renameHandleError(resp) } result := BlobRenameResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1525,9 +1650,18 @@ func (client *blobOperations) renameHandleResponse(resp *azcore.Response) (*Blob return &result, nil } +// renameHandleError handles the Rename error response. +func (client *blobOperations) renameHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // RenewLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations -func (client *blobOperations) RenewLease(ctx context.Context, leaseId string, options *BlobRenewLeaseOptions) (*BlobRenewLeaseResponse, error) { - req, err := client.renewLeaseCreateRequest(leaseId, options) +func (client *blobOperations) RenewLease(ctx context.Context, leaseId string, blobRenewLeaseOptions *BlobRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobRenewLeaseResponse, error) { + req, err := client.renewLeaseCreateRequest(leaseId, blobRenewLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -1543,32 +1677,33 @@ func (client *blobOperations) RenewLease(ctx context.Context, leaseId string, op } // renewLeaseCreateRequest creates the RenewLease request. -func (client *blobOperations) renewLeaseCreateRequest(leaseId string, options *BlobRenewLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) renewLeaseCreateRequest(leaseId string, blobRenewLeaseOptions *BlobRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobRenewLeaseOptions != nil && blobRenewLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobRenewLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "renew") req.Header.Set("x-ms-lease-id", leaseId) - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobRenewLeaseOptions != nil && blobRenewLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobRenewLeaseOptions.RequestId) } return req, nil } @@ -1576,7 +1711,7 @@ func (client *blobOperations) renewLeaseCreateRequest(leaseId string, options *B // renewLeaseHandleResponse handles the RenewLease response. func (client *blobOperations) renewLeaseHandleResponse(resp *azcore.Response) (*BlobRenewLeaseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.renewLeaseHandleError(resp) } result := BlobRenewLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1611,9 +1746,18 @@ func (client *blobOperations) renewLeaseHandleResponse(resp *azcore.Response) (* return &result, nil } +// renewLeaseHandleError handles the RenewLease error response. +func (client *blobOperations) renewLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SetAccessControl - Set the owner, group, permissions, or access control list for a blob. -func (client *blobOperations) SetAccessControl(ctx context.Context, options *BlobSetAccessControlOptions) (*BlobSetAccessControlResponse, error) { - req, err := client.setAccessControlCreateRequest(options) +func (client *blobOperations) SetAccessControl(ctx context.Context, blobSetAccessControlOptions *BlobSetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobSetAccessControlResponse, error) { + req, err := client.setAccessControlCreateRequest(blobSetAccessControlOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -1629,44 +1773,45 @@ func (client *blobOperations) SetAccessControl(ctx context.Context, options *Blo } // setAccessControlCreateRequest creates the SetAccessControl request. -func (client *blobOperations) setAccessControlCreateRequest(options *BlobSetAccessControlOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) setAccessControlCreateRequest(blobSetAccessControlOptions *BlobSetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("action", "setAccessControl") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobSetAccessControlOptions != nil && blobSetAccessControlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobSetAccessControlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPatch, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.Owner != nil { - req.Header.Set("x-ms-owner", *options.Owner) + if blobSetAccessControlOptions != nil && blobSetAccessControlOptions.Owner != nil { + req.Header.Set("x-ms-owner", *blobSetAccessControlOptions.Owner) } - if options != nil && options.Group != nil { - req.Header.Set("x-ms-group", *options.Group) + if blobSetAccessControlOptions != nil && blobSetAccessControlOptions.Group != nil { + req.Header.Set("x-ms-group", *blobSetAccessControlOptions.Group) } - if options != nil && options.PosixPermissions != nil { - req.Header.Set("x-ms-permissions", *options.PosixPermissions) + if blobSetAccessControlOptions != nil && blobSetAccessControlOptions.PosixPermissions != nil { + req.Header.Set("x-ms-permissions", *blobSetAccessControlOptions.PosixPermissions) } - if options != nil && options.PosixAcl != nil { - req.Header.Set("x-ms-acl", *options.PosixAcl) + if blobSetAccessControlOptions != nil && blobSetAccessControlOptions.PosixAcl != nil { + req.Header.Set("x-ms-acl", *blobSetAccessControlOptions.PosixAcl) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobSetAccessControlOptions != nil && blobSetAccessControlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobSetAccessControlOptions.RequestId) } req.Header.Set("x-ms-version", "2019-07-07") return req, nil @@ -1675,7 +1820,7 @@ func (client *blobOperations) setAccessControlCreateRequest(options *BlobSetAcce // setAccessControlHandleResponse handles the SetAccessControl response. func (client *blobOperations) setAccessControlHandleResponse(resp *azcore.Response) (*BlobSetAccessControlResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newDataLakeStorageError(resp) + return nil, client.setAccessControlHandleError(resp) } result := BlobSetAccessControlResponse{RawResponse: resp.Response} if val := resp.Header.Get("Date"); val != "" { @@ -1704,9 +1849,18 @@ func (client *blobOperations) setAccessControlHandleResponse(resp *azcore.Respon return &result, nil } +// setAccessControlHandleError handles the SetAccessControl error response. +func (client *blobOperations) setAccessControlHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SetHTTPHeaders - The Set HTTP Headers operation sets system properties on the blob -func (client *blobOperations) SetHTTPHeaders(ctx context.Context, options *BlobSetHTTPHeadersOptions) (*BlobSetHTTPHeadersResponse, error) { - req, err := client.setHttpHeadersCreateRequest(options) +func (client *blobOperations) SetHTTPHeaders(ctx context.Context, blobSetHttpHeadersOptions *BlobSetHTTPHeadersOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*BlobSetHTTPHeadersResponse, error) { + req, err := client.setHttpHeadersCreateRequest(blobSetHttpHeadersOptions, blobHttpHeaders, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -1722,51 +1876,52 @@ func (client *blobOperations) SetHTTPHeaders(ctx context.Context, options *BlobS } // setHttpHeadersCreateRequest creates the SetHTTPHeaders request. -func (client *blobOperations) setHttpHeadersCreateRequest(options *BlobSetHTTPHeadersOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) setHttpHeadersCreateRequest(blobSetHttpHeadersOptions *BlobSetHTTPHeadersOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "properties") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobSetHttpHeadersOptions != nil && blobSetHttpHeadersOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobSetHttpHeadersOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.BlobCacheControl != nil { - req.Header.Set("x-ms-blob-cache-control", *options.BlobCacheControl) + if blobHttpHeaders != nil && blobHttpHeaders.BlobCacheControl != nil { + req.Header.Set("x-ms-blob-cache-control", *blobHttpHeaders.BlobCacheControl) } - if options != nil && options.BlobContentType != nil { - req.Header.Set("x-ms-blob-content-type", *options.BlobContentType) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentType != nil { + req.Header.Set("x-ms-blob-content-type", *blobHttpHeaders.BlobContentType) } - if options != nil && options.BlobContentMd5 != nil { - req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*options.BlobContentMd5)) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentMd5 != nil { + req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*blobHttpHeaders.BlobContentMd5)) } - if options != nil && options.BlobContentEncoding != nil { - req.Header.Set("x-ms-blob-content-encoding", *options.BlobContentEncoding) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentEncoding != nil { + req.Header.Set("x-ms-blob-content-encoding", *blobHttpHeaders.BlobContentEncoding) } - if options != nil && options.BlobContentLanguage != nil { - req.Header.Set("x-ms-blob-content-language", *options.BlobContentLanguage) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentLanguage != nil { + req.Header.Set("x-ms-blob-content-language", *blobHttpHeaders.BlobContentLanguage) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.BlobContentDisposition != nil { - req.Header.Set("x-ms-blob-content-disposition", *options.BlobContentDisposition) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentDisposition != nil { + req.Header.Set("x-ms-blob-content-disposition", *blobHttpHeaders.BlobContentDisposition) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobSetHttpHeadersOptions != nil && blobSetHttpHeadersOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobSetHttpHeadersOptions.RequestId) } return req, nil } @@ -1774,7 +1929,7 @@ func (client *blobOperations) setHttpHeadersCreateRequest(options *BlobSetHTTPHe // setHttpHeadersHandleResponse handles the SetHTTPHeaders response. func (client *blobOperations) setHttpHeadersHandleResponse(resp *azcore.Response) (*BlobSetHTTPHeadersResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.setHttpHeadersHandleError(resp) } result := BlobSetHTTPHeadersResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1813,9 +1968,18 @@ func (client *blobOperations) setHttpHeadersHandleResponse(resp *azcore.Response return &result, nil } +// setHttpHeadersHandleError handles the SetHTTPHeaders error response. +func (client *blobOperations) setHttpHeadersHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SetMetadata - The Set Blob Metadata operation sets user-defined metadata for the specified blob as one or more name-value pairs -func (client *blobOperations) SetMetadata(ctx context.Context, options *BlobSetMetadataOptions) (*BlobSetMetadataResponse, error) { - req, err := client.setMetadataCreateRequest(options) +func (client *blobOperations) SetMetadata(ctx context.Context, blobSetMetadataOptions *BlobSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlobSetMetadataResponse, error) { + req, err := client.setMetadataCreateRequest(blobSetMetadataOptions, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -1831,45 +1995,48 @@ func (client *blobOperations) SetMetadata(ctx context.Context, options *BlobSetM } // setMetadataCreateRequest creates the SetMetadata request. -func (client *blobOperations) setMetadataCreateRequest(options *BlobSetMetadataOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) setMetadataCreateRequest(blobSetMetadataOptions *BlobSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "metadata") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobSetMetadataOptions != nil && blobSetMetadataOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobSetMetadataOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if blobSetMetadataOptions != nil && blobSetMetadataOptions.Metadata != nil { + for k, v := range *blobSetMetadataOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobSetMetadataOptions != nil && blobSetMetadataOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobSetMetadataOptions.RequestId) } return req, nil } @@ -1877,7 +2044,7 @@ func (client *blobOperations) setMetadataCreateRequest(options *BlobSetMetadataO // setMetadataHandleResponse handles the SetMetadata response. func (client *blobOperations) setMetadataHandleResponse(resp *azcore.Response) (*BlobSetMetadataResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.setMetadataHandleError(resp) } result := BlobSetMetadataResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1922,9 +2089,18 @@ func (client *blobOperations) setMetadataHandleResponse(resp *azcore.Response) ( return &result, nil } +// setMetadataHandleError handles the SetMetadata error response. +func (client *blobOperations) setMetadataHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *blobOperations) SetTier(ctx context.Context, tier AccessTier, options *BlobSetTierOptions) (*BlobSetTierResponse, error) { - req, err := client.setTierCreateRequest(tier, options) +func (client *blobOperations) SetTier(ctx context.Context, tier AccessTier, blobSetTierOptions *BlobSetTierOptions, leaseAccessConditions *LeaseAccessConditions) (*BlobSetTierResponse, error) { + req, err := client.setTierCreateRequest(tier, blobSetTierOptions, leaseAccessConditions) if err != nil { return nil, err } @@ -1940,33 +2116,34 @@ func (client *blobOperations) SetTier(ctx context.Context, tier AccessTier, opti } // setTierCreateRequest creates the SetTier request. -func (client *blobOperations) setTierCreateRequest(tier AccessTier, options *BlobSetTierOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) setTierCreateRequest(tier AccessTier, blobSetTierOptions *BlobSetTierOptions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "tier") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobSetTierOptions != nil && blobSetTierOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobSetTierOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-access-tier", string(tier)) - if options != nil && options.RehydratePriority != nil { - req.Header.Set("x-ms-rehydrate-priority", string(*options.RehydratePriority)) + if blobSetTierOptions != nil && blobSetTierOptions.RehydratePriority != nil { + req.Header.Set("x-ms-rehydrate-priority", string(*blobSetTierOptions.RehydratePriority)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobSetTierOptions != nil && blobSetTierOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobSetTierOptions.RequestId) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } return req, nil } // setTierHandleResponse handles the SetTier response. func (client *blobOperations) setTierHandleResponse(resp *azcore.Response) (*BlobSetTierResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + if !resp.HasStatusCode(http.StatusOK, http.StatusAccepted) { + return nil, client.setTierHandleError(resp) } result := BlobSetTierResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -1981,9 +2158,18 @@ func (client *blobOperations) setTierHandleResponse(resp *azcore.Response) (*Blo return &result, nil } +// setTierHandleError handles the SetTier error response. +func (client *blobOperations) setTierHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // StartCopyFromURL - The Start Copy From URL operation copies a blob or an internet resource to a new blob. -func (client *blobOperations) StartCopyFromURL(ctx context.Context, copySource url.URL, options *BlobStartCopyFromURLOptions) (*BlobStartCopyFromURLResponse, error) { - req, err := client.startCopyFromUrlCreateRequest(copySource, options) +func (client *blobOperations) StartCopyFromURL(ctx context.Context, copySource url.URL, blobStartCopyFromUrlOptions *BlobStartCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*BlobStartCopyFromURLResponse, error) { + req, err := client.startCopyFromUrlCreateRequest(copySource, blobStartCopyFromUrlOptions, sourceModifiedAccessConditions, modifiedAccessConditions, leaseAccessConditions) if err != nil { return nil, err } @@ -1999,54 +2185,57 @@ func (client *blobOperations) StartCopyFromURL(ctx context.Context, copySource u } // startCopyFromUrlCreateRequest creates the StartCopyFromURL request. -func (client *blobOperations) startCopyFromUrlCreateRequest(copySource url.URL, options *BlobStartCopyFromURLOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) startCopyFromUrlCreateRequest(copySource url.URL, blobStartCopyFromUrlOptions *BlobStartCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobStartCopyFromUrlOptions != nil && blobStartCopyFromUrlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobStartCopyFromUrlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if blobStartCopyFromUrlOptions != nil && blobStartCopyFromUrlOptions.Metadata != nil { + for k, v := range *blobStartCopyFromUrlOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.Tier != nil { - req.Header.Set("x-ms-access-tier", string(*options.Tier)) + if blobStartCopyFromUrlOptions != nil && blobStartCopyFromUrlOptions.Tier != nil { + req.Header.Set("x-ms-access-tier", string(*blobStartCopyFromUrlOptions.Tier)) } - if options != nil && options.RehydratePriority != nil { - req.Header.Set("x-ms-rehydrate-priority", string(*options.RehydratePriority)) + if blobStartCopyFromUrlOptions != nil && blobStartCopyFromUrlOptions.RehydratePriority != nil { + req.Header.Set("x-ms-rehydrate-priority", string(*blobStartCopyFromUrlOptions.RehydratePriority)) } - if options != nil && options.SourceIfModifiedSince != nil { - req.Header.Set("x-ms-source-if-modified-since", options.SourceIfModifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Header.Set("x-ms-source-if-modified-since", sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfUnmodifiedSince != nil { - req.Header.Set("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Header.Set("x-ms-source-if-unmodified-since", sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfMatch != nil { - req.Header.Set("x-ms-source-if-match", *options.SourceIfMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Header.Set("x-ms-source-if-match", *sourceModifiedAccessConditions.SourceIfMatch) } - if options != nil && options.SourceIfNoneMatch != nil { - req.Header.Set("x-ms-source-if-none-match", *options.SourceIfNoneMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Header.Set("x-ms-source-if-none-match", *sourceModifiedAccessConditions.SourceIfNoneMatch) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-copy-source", copySource.String()) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobStartCopyFromUrlOptions != nil && blobStartCopyFromUrlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobStartCopyFromUrlOptions.RequestId) } return req, nil } @@ -2054,7 +2243,7 @@ func (client *blobOperations) startCopyFromUrlCreateRequest(copySource url.URL, // startCopyFromUrlHandleResponse handles the StartCopyFromURL response. func (client *blobOperations) startCopyFromUrlHandleResponse(resp *azcore.Response) (*BlobStartCopyFromURLResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.startCopyFromUrlHandleError(resp) } result := BlobStartCopyFromURLResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -2092,9 +2281,18 @@ func (client *blobOperations) startCopyFromUrlHandleResponse(resp *azcore.Respon return &result, nil } +// startCopyFromUrlHandleError handles the StartCopyFromURL error response. +func (client *blobOperations) startCopyFromUrlHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Undelete - Undelete a blob that was previously soft deleted -func (client *blobOperations) Undelete(ctx context.Context, options *BlobUndeleteOptions) (*BlobUndeleteResponse, error) { - req, err := client.undeleteCreateRequest(options) +func (client *blobOperations) Undelete(ctx context.Context, blobUndeleteOptions *BlobUndeleteOptions) (*BlobUndeleteResponse, error) { + req, err := client.undeleteCreateRequest(blobUndeleteOptions) if err != nil { return nil, err } @@ -2110,18 +2308,19 @@ func (client *blobOperations) Undelete(ctx context.Context, options *BlobUndelet } // undeleteCreateRequest creates the Undelete request. -func (client *blobOperations) undeleteCreateRequest(options *BlobUndeleteOptions) (*azcore.Request, error) { - u := client.u +func (client *blobOperations) undeleteCreateRequest(blobUndeleteOptions *BlobUndeleteOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "undelete") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blobUndeleteOptions != nil && blobUndeleteOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blobUndeleteOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blobUndeleteOptions != nil && blobUndeleteOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blobUndeleteOptions.RequestId) } return req, nil } @@ -2129,7 +2328,7 @@ func (client *blobOperations) undeleteCreateRequest(options *BlobUndeleteOptions // undeleteHandleResponse handles the Undelete response. func (client *blobOperations) undeleteHandleResponse(resp *azcore.Response) (*BlobUndeleteResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.undeleteHandleError(resp) } result := BlobUndeleteResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -2150,3 +2349,12 @@ func (client *blobOperations) undeleteHandleResponse(resp *azcore.Response) (*Bl } return &result, nil } + +// undeleteHandleError handles the Undelete error response. +func (client *blobOperations) undeleteHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} diff --git a/sdk/storage/blob/2019-07-07/azblob/blockblob.go b/sdk/storage/blob/2019-07-07/azblob/blockblob.go index c0ad16dafce0..049df94674bf 100644 --- a/sdk/storage/blob/2019-07-07/azblob/blockblob.go +++ b/sdk/storage/blob/2019-07-07/azblob/blockblob.go @@ -18,25 +18,25 @@ import ( // BlockBlobOperations contains the methods for the BlockBlob group. type BlockBlobOperations interface { // 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. - CommitBlockList(ctx context.Context, blocks BlockLookupList, options *BlockBlobCommitBlockListOptions) (*BlockBlobCommitBlockListResponse, error) + CommitBlockList(ctx context.Context, blocks BlockLookupList, blockBlobCommitBlockListOptions *BlockBlobCommitBlockListOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlockBlobCommitBlockListResponse, error) // GetBlockList - The Get Block List operation retrieves the list of blocks that have been uploaded as part of a block blob - GetBlockList(ctx context.Context, listType BlockListType, options *BlockBlobGetBlockListOptions) (*BlockListResponse, error) + GetBlockList(ctx context.Context, listType BlockListType, blockBlobGetBlockListOptions *BlockBlobGetBlockListOptions, leaseAccessConditions *LeaseAccessConditions) (*BlockListResponse, error) // StageBlock - The Stage Block operation creates a new block to be committed as part of a blob - StageBlock(ctx context.Context, blockId string, contentLength int64, body azcore.ReadSeekCloser, options *BlockBlobStageBlockOptions) (*BlockBlobStageBlockResponse, error) + StageBlock(ctx context.Context, blockId string, contentLength int64, body azcore.ReadSeekCloser, blockBlobStageBlockOptions *BlockBlobStageBlockOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo) (*BlockBlobStageBlockResponse, error) // 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. - StageBlockFromURL(ctx context.Context, blockId string, contentLength int64, sourceUrl url.URL, options *BlockBlobStageBlockFromURLOptions) (*BlockBlobStageBlockFromURLResponse, error) + StageBlockFromURL(ctx context.Context, blockId string, contentLength int64, sourceUrl url.URL, blockBlobStageBlockFromUrlOptions *BlockBlobStageBlockFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*BlockBlobStageBlockFromURLResponse, error) // 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. - Upload(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, options *BlockBlobUploadOptions) (*BlockBlobUploadResponse, error) + Upload(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, blockBlobUploadOptions *BlockBlobUploadOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlockBlobUploadResponse, error) } // blockBlobOperations implements the BlockBlobOperations interface. type blockBlobOperations struct { - *Client + *client } // 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. -func (client *blockBlobOperations) CommitBlockList(ctx context.Context, blocks BlockLookupList, options *BlockBlobCommitBlockListOptions) (*BlockBlobCommitBlockListResponse, error) { - req, err := client.commitBlockListCreateRequest(blocks, options) +func (client *blockBlobOperations) CommitBlockList(ctx context.Context, blocks BlockLookupList, blockBlobCommitBlockListOptions *BlockBlobCommitBlockListOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlockBlobCommitBlockListResponse, error) { + req, err := client.commitBlockListCreateRequest(blocks, blockBlobCommitBlockListOptions, blobHttpHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -52,72 +52,75 @@ func (client *blockBlobOperations) CommitBlockList(ctx context.Context, blocks B } // commitBlockListCreateRequest creates the CommitBlockList request. -func (client *blockBlobOperations) commitBlockListCreateRequest(blocks BlockLookupList, options *BlockBlobCommitBlockListOptions) (*azcore.Request, error) { - u := client.u +func (client *blockBlobOperations) commitBlockListCreateRequest(blocks BlockLookupList, blockBlobCommitBlockListOptions *BlockBlobCommitBlockListOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "blocklist") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blockBlobCommitBlockListOptions != nil && blockBlobCommitBlockListOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blockBlobCommitBlockListOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.BlobCacheControl != nil { - req.Header.Set("x-ms-blob-cache-control", *options.BlobCacheControl) + if blobHttpHeaders != nil && blobHttpHeaders.BlobCacheControl != nil { + req.Header.Set("x-ms-blob-cache-control", *blobHttpHeaders.BlobCacheControl) } - if options != nil && options.BlobContentType != nil { - req.Header.Set("x-ms-blob-content-type", *options.BlobContentType) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentType != nil { + req.Header.Set("x-ms-blob-content-type", *blobHttpHeaders.BlobContentType) } - if options != nil && options.BlobContentEncoding != nil { - req.Header.Set("x-ms-blob-content-encoding", *options.BlobContentEncoding) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentEncoding != nil { + req.Header.Set("x-ms-blob-content-encoding", *blobHttpHeaders.BlobContentEncoding) } - if options != nil && options.BlobContentLanguage != nil { - req.Header.Set("x-ms-blob-content-language", *options.BlobContentLanguage) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentLanguage != nil { + req.Header.Set("x-ms-blob-content-language", *blobHttpHeaders.BlobContentLanguage) } - if options != nil && options.BlobContentMd5 != nil { - req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*options.BlobContentMd5)) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentMd5 != nil { + req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*blobHttpHeaders.BlobContentMd5)) } - if options != nil && options.TransactionalContentMd5 != nil { - req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*options.TransactionalContentMd5)) + if blockBlobCommitBlockListOptions != nil && blockBlobCommitBlockListOptions.TransactionalContentMd5 != nil { + req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*blockBlobCommitBlockListOptions.TransactionalContentMd5)) } - if options != nil && options.TransactionalContentCrc64 != nil { - req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*options.TransactionalContentCrc64)) + if blockBlobCommitBlockListOptions != nil && blockBlobCommitBlockListOptions.TransactionalContentCrc64 != nil { + req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*blockBlobCommitBlockListOptions.TransactionalContentCrc64)) } - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if blockBlobCommitBlockListOptions != nil && blockBlobCommitBlockListOptions.Metadata != nil { + for k, v := range *blockBlobCommitBlockListOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.BlobContentDisposition != nil { - req.Header.Set("x-ms-blob-content-disposition", *options.BlobContentDisposition) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentDisposition != nil { + req.Header.Set("x-ms-blob-content-disposition", *blobHttpHeaders.BlobContentDisposition) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.Tier != nil { - req.Header.Set("x-ms-access-tier", string(*options.Tier)) + if blockBlobCommitBlockListOptions != nil && blockBlobCommitBlockListOptions.Tier != nil { + req.Header.Set("x-ms-access-tier", string(*blockBlobCommitBlockListOptions.Tier)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blockBlobCommitBlockListOptions != nil && blockBlobCommitBlockListOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blockBlobCommitBlockListOptions.RequestId) } return req, req.MarshalAsXML(blocks) } @@ -125,7 +128,7 @@ func (client *blockBlobOperations) commitBlockListCreateRequest(blocks BlockLook // commitBlockListHandleResponse handles the CommitBlockList response. func (client *blockBlobOperations) commitBlockListHandleResponse(resp *azcore.Response) (*BlockBlobCommitBlockListResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.commitBlockListHandleError(resp) } result := BlockBlobCommitBlockListResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -184,9 +187,18 @@ func (client *blockBlobOperations) commitBlockListHandleResponse(resp *azcore.Re return &result, nil } +// commitBlockListHandleError handles the CommitBlockList error response. +func (client *blockBlobOperations) commitBlockListHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetBlockList - The Get Block List operation retrieves the list of blocks that have been uploaded as part of a block blob -func (client *blockBlobOperations) GetBlockList(ctx context.Context, listType BlockListType, options *BlockBlobGetBlockListOptions) (*BlockListResponse, error) { - req, err := client.getBlockListCreateRequest(listType, options) +func (client *blockBlobOperations) GetBlockList(ctx context.Context, listType BlockListType, blockBlobGetBlockListOptions *BlockBlobGetBlockListOptions, leaseAccessConditions *LeaseAccessConditions) (*BlockListResponse, error) { + req, err := client.getBlockListCreateRequest(listType, blockBlobGetBlockListOptions, leaseAccessConditions) if err != nil { return nil, err } @@ -202,25 +214,26 @@ func (client *blockBlobOperations) GetBlockList(ctx context.Context, listType Bl } // getBlockListCreateRequest creates the GetBlockList request. -func (client *blockBlobOperations) getBlockListCreateRequest(listType BlockListType, options *BlockBlobGetBlockListOptions) (*azcore.Request, error) { - u := client.u +func (client *blockBlobOperations) getBlockListCreateRequest(listType BlockListType, blockBlobGetBlockListOptions *BlockBlobGetBlockListOptions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "blocklist") - if options != nil && options.Snapshot != nil { - query.Set("snapshot", *options.Snapshot) + if blockBlobGetBlockListOptions != nil && blockBlobGetBlockListOptions.Snapshot != nil { + query.Set("snapshot", *blockBlobGetBlockListOptions.Snapshot) } query.Set("blocklisttype", string(listType)) - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blockBlobGetBlockListOptions != nil && blockBlobGetBlockListOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blockBlobGetBlockListOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blockBlobGetBlockListOptions != nil && blockBlobGetBlockListOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blockBlobGetBlockListOptions.RequestId) } return req, nil } @@ -228,7 +241,7 @@ func (client *blockBlobOperations) getBlockListCreateRequest(listType BlockListT // getBlockListHandleResponse handles the GetBlockList response. func (client *blockBlobOperations) getBlockListHandleResponse(resp *azcore.Response) (*BlockListResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getBlockListHandleError(resp) } result := BlockListResponse{RawResponse: resp.Response} if val := resp.Header.Get("Last-Modified"); val != "" { @@ -270,9 +283,18 @@ func (client *blockBlobOperations) getBlockListHandleResponse(resp *azcore.Respo return &result, resp.UnmarshalAsXML(&result.BlockList) } +// getBlockListHandleError handles the GetBlockList error response. +func (client *blockBlobOperations) getBlockListHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // StageBlock - The Stage Block operation creates a new block to be committed as part of a blob -func (client *blockBlobOperations) StageBlock(ctx context.Context, blockId string, contentLength int64, body azcore.ReadSeekCloser, options *BlockBlobStageBlockOptions) (*BlockBlobStageBlockResponse, error) { - req, err := client.stageBlockCreateRequest(blockId, contentLength, body, options) +func (client *blockBlobOperations) StageBlock(ctx context.Context, blockId string, contentLength int64, body azcore.ReadSeekCloser, blockBlobStageBlockOptions *BlockBlobStageBlockOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo) (*BlockBlobStageBlockResponse, error) { + req, err := client.stageBlockCreateRequest(blockId, contentLength, body, blockBlobStageBlockOptions, leaseAccessConditions, cpkInfo, cpkScopeInfo) if err != nil { return nil, err } @@ -288,38 +310,39 @@ func (client *blockBlobOperations) StageBlock(ctx context.Context, blockId strin } // stageBlockCreateRequest creates the StageBlock request. -func (client *blockBlobOperations) stageBlockCreateRequest(blockId string, contentLength int64, body azcore.ReadSeekCloser, options *BlockBlobStageBlockOptions) (*azcore.Request, error) { - u := client.u +func (client *blockBlobOperations) stageBlockCreateRequest(blockId string, contentLength int64, body azcore.ReadSeekCloser, blockBlobStageBlockOptions *BlockBlobStageBlockOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "block") query.Set("blockid", blockId) - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blockBlobStageBlockOptions != nil && blockBlobStageBlockOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blockBlobStageBlockOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.TransactionalContentMd5 != nil { - req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*options.TransactionalContentMd5)) + if blockBlobStageBlockOptions != nil && blockBlobStageBlockOptions.TransactionalContentMd5 != nil { + req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*blockBlobStageBlockOptions.TransactionalContentMd5)) } - if options != nil && options.TransactionalContentCrc64 != nil { - req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*options.TransactionalContentCrc64)) + if blockBlobStageBlockOptions != nil && blockBlobStageBlockOptions.TransactionalContentCrc64 != nil { + req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*blockBlobStageBlockOptions.TransactionalContentCrc64)) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blockBlobStageBlockOptions != nil && blockBlobStageBlockOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blockBlobStageBlockOptions.RequestId) } return req, req.SetBody(body) } @@ -327,7 +350,7 @@ func (client *blockBlobOperations) stageBlockCreateRequest(blockId string, conte // stageBlockHandleResponse handles the StageBlock response. func (client *blockBlobOperations) stageBlockHandleResponse(resp *azcore.Response) (*BlockBlobStageBlockResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.stageBlockHandleError(resp) } result := BlockBlobStageBlockResponse{RawResponse: resp.Response} if val := resp.Header.Get("Content-MD5"); val != "" { @@ -376,9 +399,18 @@ func (client *blockBlobOperations) stageBlockHandleResponse(resp *azcore.Respons return &result, nil } +// stageBlockHandleError handles the StageBlock error response. +func (client *blockBlobOperations) stageBlockHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *blockBlobOperations) StageBlockFromURL(ctx context.Context, blockId string, contentLength int64, sourceUrl url.URL, options *BlockBlobStageBlockFromURLOptions) (*BlockBlobStageBlockFromURLResponse, error) { - req, err := client.stageBlockFromUrlCreateRequest(blockId, contentLength, sourceUrl, options) +func (client *blockBlobOperations) StageBlockFromURL(ctx context.Context, blockId string, contentLength int64, sourceUrl url.URL, blockBlobStageBlockFromUrlOptions *BlockBlobStageBlockFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*BlockBlobStageBlockFromURLResponse, error) { + req, err := client.stageBlockFromUrlCreateRequest(blockId, contentLength, sourceUrl, blockBlobStageBlockFromUrlOptions, cpkInfo, cpkScopeInfo, leaseAccessConditions, sourceModifiedAccessConditions) if err != nil { return nil, err } @@ -394,54 +426,55 @@ func (client *blockBlobOperations) StageBlockFromURL(ctx context.Context, blockI } // stageBlockFromUrlCreateRequest creates the StageBlockFromURL request. -func (client *blockBlobOperations) stageBlockFromUrlCreateRequest(blockId string, contentLength int64, sourceUrl url.URL, options *BlockBlobStageBlockFromURLOptions) (*azcore.Request, error) { - u := client.u +func (client *blockBlobOperations) stageBlockFromUrlCreateRequest(blockId string, contentLength int64, sourceUrl url.URL, blockBlobStageBlockFromUrlOptions *BlockBlobStageBlockFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "block") query.Set("blockid", blockId) - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blockBlobStageBlockFromUrlOptions != nil && blockBlobStageBlockFromUrlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blockBlobStageBlockFromUrlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) req.Header.Set("x-ms-copy-source", sourceUrl.String()) - if options != nil && options.SourceRange != nil { - req.Header.Set("x-ms-source-range", *options.SourceRange) + if blockBlobStageBlockFromUrlOptions != nil && blockBlobStageBlockFromUrlOptions.SourceRange != nil { + req.Header.Set("x-ms-source-range", *blockBlobStageBlockFromUrlOptions.SourceRange) } - if options != nil && options.SourceContentMd5 != nil { - req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*options.SourceContentMd5)) + if blockBlobStageBlockFromUrlOptions != nil && blockBlobStageBlockFromUrlOptions.SourceContentMd5 != nil { + req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*blockBlobStageBlockFromUrlOptions.SourceContentMd5)) } - if options != nil && options.SourceContentcrc64 != nil { - req.Header.Set("x-ms-source-content-crc64", base64.StdEncoding.EncodeToString(*options.SourceContentcrc64)) + if blockBlobStageBlockFromUrlOptions != nil && blockBlobStageBlockFromUrlOptions.SourceContentcrc64 != nil { + req.Header.Set("x-ms-source-content-crc64", base64.StdEncoding.EncodeToString(*blockBlobStageBlockFromUrlOptions.SourceContentcrc64)) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.SourceIfModifiedSince != nil { - req.Header.Set("x-ms-source-if-modified-since", options.SourceIfModifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Header.Set("x-ms-source-if-modified-since", sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfUnmodifiedSince != nil { - req.Header.Set("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Header.Set("x-ms-source-if-unmodified-since", sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfMatch != nil { - req.Header.Set("x-ms-source-if-match", *options.SourceIfMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Header.Set("x-ms-source-if-match", *sourceModifiedAccessConditions.SourceIfMatch) } - if options != nil && options.SourceIfNoneMatch != nil { - req.Header.Set("x-ms-source-if-none-match", *options.SourceIfNoneMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Header.Set("x-ms-source-if-none-match", *sourceModifiedAccessConditions.SourceIfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blockBlobStageBlockFromUrlOptions != nil && blockBlobStageBlockFromUrlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blockBlobStageBlockFromUrlOptions.RequestId) } return req, nil } @@ -449,7 +482,7 @@ func (client *blockBlobOperations) stageBlockFromUrlCreateRequest(blockId string // stageBlockFromUrlHandleResponse handles the StageBlockFromURL response. func (client *blockBlobOperations) stageBlockFromUrlHandleResponse(resp *azcore.Response) (*BlockBlobStageBlockFromURLResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.stageBlockFromUrlHandleError(resp) } result := BlockBlobStageBlockFromURLResponse{RawResponse: resp.Response} if val := resp.Header.Get("Content-MD5"); val != "" { @@ -498,9 +531,18 @@ func (client *blockBlobOperations) stageBlockFromUrlHandleResponse(resp *azcore. return &result, nil } +// stageBlockFromUrlHandleError handles the StageBlockFromURL error response. +func (client *blockBlobOperations) stageBlockFromUrlHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *blockBlobOperations) Upload(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, options *BlockBlobUploadOptions) (*BlockBlobUploadResponse, error) { - req, err := client.uploadCreateRequest(contentLength, body, options) +func (client *blockBlobOperations) Upload(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, blockBlobUploadOptions *BlockBlobUploadOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*BlockBlobUploadResponse, error) { + req, err := client.uploadCreateRequest(contentLength, body, blockBlobUploadOptions, blobHttpHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -516,70 +558,73 @@ func (client *blockBlobOperations) Upload(ctx context.Context, contentLength int } // uploadCreateRequest creates the Upload request. -func (client *blockBlobOperations) uploadCreateRequest(contentLength int64, body azcore.ReadSeekCloser, options *BlockBlobUploadOptions) (*azcore.Request, error) { - u := client.u +func (client *blockBlobOperations) uploadCreateRequest(contentLength int64, body azcore.ReadSeekCloser, blockBlobUploadOptions *BlockBlobUploadOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if blockBlobUploadOptions != nil && blockBlobUploadOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*blockBlobUploadOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-blob-type", "BlockBlob") - if options != nil && options.TransactionalContentMd5 != nil { - req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*options.TransactionalContentMd5)) + if blockBlobUploadOptions != nil && blockBlobUploadOptions.TransactionalContentMd5 != nil { + req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*blockBlobUploadOptions.TransactionalContentMd5)) } req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.BlobContentType != nil { - req.Header.Set("x-ms-blob-content-type", *options.BlobContentType) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentType != nil { + req.Header.Set("x-ms-blob-content-type", *blobHttpHeaders.BlobContentType) } - if options != nil && options.BlobContentEncoding != nil { - req.Header.Set("x-ms-blob-content-encoding", *options.BlobContentEncoding) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentEncoding != nil { + req.Header.Set("x-ms-blob-content-encoding", *blobHttpHeaders.BlobContentEncoding) } - if options != nil && options.BlobContentLanguage != nil { - req.Header.Set("x-ms-blob-content-language", *options.BlobContentLanguage) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentLanguage != nil { + req.Header.Set("x-ms-blob-content-language", *blobHttpHeaders.BlobContentLanguage) } - if options != nil && options.BlobContentMd5 != nil { - req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*options.BlobContentMd5)) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentMd5 != nil { + req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*blobHttpHeaders.BlobContentMd5)) } - if options != nil && options.BlobCacheControl != nil { - req.Header.Set("x-ms-blob-cache-control", *options.BlobCacheControl) + if blobHttpHeaders != nil && blobHttpHeaders.BlobCacheControl != nil { + req.Header.Set("x-ms-blob-cache-control", *blobHttpHeaders.BlobCacheControl) } - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if blockBlobUploadOptions != nil && blockBlobUploadOptions.Metadata != nil { + for k, v := range *blockBlobUploadOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.BlobContentDisposition != nil { - req.Header.Set("x-ms-blob-content-disposition", *options.BlobContentDisposition) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentDisposition != nil { + req.Header.Set("x-ms-blob-content-disposition", *blobHttpHeaders.BlobContentDisposition) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.Tier != nil { - req.Header.Set("x-ms-access-tier", string(*options.Tier)) + if blockBlobUploadOptions != nil && blockBlobUploadOptions.Tier != nil { + req.Header.Set("x-ms-access-tier", string(*blockBlobUploadOptions.Tier)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if blockBlobUploadOptions != nil && blockBlobUploadOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *blockBlobUploadOptions.RequestId) } return req, req.SetBody(body) } @@ -587,7 +632,7 @@ func (client *blockBlobOperations) uploadCreateRequest(contentLength int64, body // uploadHandleResponse handles the Upload response. func (client *blockBlobOperations) uploadHandleResponse(resp *azcore.Response) (*BlockBlobUploadResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.uploadHandleError(resp) } result := BlockBlobUploadResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -638,3 +683,12 @@ func (client *blockBlobOperations) uploadHandleResponse(resp *azcore.Response) ( } return &result, nil } + +// uploadHandleError handles the Upload error response. +func (client *blockBlobOperations) uploadHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} diff --git a/sdk/storage/blob/2019-07-07/azblob/client.go b/sdk/storage/blob/2019-07-07/azblob/client.go index a04c77ea2586..c3e04a2b6a25 100644 --- a/sdk/storage/blob/2019-07-07/azblob/client.go +++ b/sdk/storage/blob/2019-07-07/azblob/client.go @@ -7,16 +7,16 @@ package azblob import ( "fmt" - "net/url" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "net/url" + "strings" ) -const ( - scope = "https://storage.azure.com/.default" -) +const scope = "https://storage.azure.com/.default" +const telemetryInfo = "azsdk-go-azblob/" -type ClientOptions struct { +// clientOptions contains configuration settings for the default client's pipeline. +type clientOptions struct { // HTTPClient sets the transport for making HTTP requests. HTTPClient azcore.Transport // LogOptions configures the built-in request logging policy behavior. @@ -25,38 +25,56 @@ type ClientOptions struct { Retry azcore.RetryOptions // Telemetry configures the built-in telemetry policy behavior. Telemetry azcore.TelemetryOptions + // ApplicationID is an application-specific identification string used in telemetry. + // It has a maximum length of 24 characters and must not contain any spaces. + ApplicationID string } -// DefaultClientOptions creates a ClientOptions type initialized with default values. -func DefaultClientOptions() ClientOptions { - return ClientOptions{ +// defaultClientOptions creates a clientOptions type initialized with default values. +func defaultClientOptions() clientOptions { + return clientOptions{ HTTPClient: azcore.DefaultHTTPClientTransport(), Retry: azcore.DefaultRetryOptions(), } } -type Client struct { +func (c *clientOptions) telemetryOptions() azcore.TelemetryOptions { + t := telemetryInfo + if c.ApplicationID != "" { + a := strings.ReplaceAll(c.ApplicationID, " ", "/") + if len(a) > 24 { + a = a[:24] + } + t = fmt.Sprintf("%s %s", a, telemetryInfo) + } + if c.Telemetry.Value == "" { + return azcore.TelemetryOptions{Value: t} + } + return azcore.TelemetryOptions{Value: fmt.Sprintf("%s %s", c.Telemetry.Value, t)} +} + +type client struct { u *url.URL p azcore.Pipeline } -// NewClient creates an instance of the Client type with the specified endpoint. -func NewClient(endpoint string, cred azcore.Credential, options *ClientOptions) (*Client, error) { +// newClient creates an instance of the client type with the specified endpoint. +func newClient(endpoint string, cred azcore.Credential, options *clientOptions) (*client, error) { if options == nil { - o := DefaultClientOptions() + o := defaultClientOptions() options = &o } p := azcore.NewPipeline(options.HTTPClient, - azcore.NewTelemetryPolicy(options.Telemetry), + azcore.NewTelemetryPolicy(options.telemetryOptions()), azcore.NewUniqueRequestIDPolicy(), azcore.NewRetryPolicy(&options.Retry), cred.AuthenticationPolicy(azcore.AuthenticationPolicyOptions{Options: azcore.TokenRequestOptions{Scopes: []string{scope}}}), azcore.NewRequestLogPolicy(options.LogOptions)) - return NewClientWithPipeline(endpoint, p) + return newClientWithPipeline(endpoint, p) } -// NewClientWithPipeline creates an instance of the Client type with the specified endpoint and pipeline. -func NewClientWithPipeline(endpoint string, p azcore.Pipeline) (*Client, error) { +// newClientWithPipeline creates an instance of the client type with the specified endpoint and pipeline. +func newClientWithPipeline(endpoint string, p azcore.Pipeline) (*client, error) { u, err := url.Parse(endpoint) if err != nil { return nil, err @@ -64,40 +82,40 @@ func NewClientWithPipeline(endpoint string, p azcore.Pipeline) (*Client, error) if u.Scheme == "" { return nil, fmt.Errorf("no scheme detected in endpoint %s", endpoint) } - return &Client{u: u, p: p}, nil + return &client{u: u, p: p}, nil } // ServiceOperations returns the ServiceOperations associated with this client. -func (client *Client) ServiceOperations() ServiceOperations { - return &serviceOperations{Client: client} +func (client *client) ServiceOperations() ServiceOperations { + return &serviceOperations{client: client} } // ContainerOperations returns the ContainerOperations associated with this client. -func (client *Client) ContainerOperations() ContainerOperations { - return &containerOperations{Client: client} +func (client *client) ContainerOperations() ContainerOperations { + return &containerOperations{client: client} } // DirectoryOperations returns the DirectoryOperations associated with this client. -func (client *Client) DirectoryOperations(pathRenameMode *PathRenameMode) DirectoryOperations { - return &directoryOperations{Client: client, pathRenameMode: pathRenameMode} +func (client *client) DirectoryOperations(pathRenameMode *PathRenameMode) DirectoryOperations { + return &directoryOperations{client: client, pathRenameMode: pathRenameMode} } // BlobOperations returns the BlobOperations associated with this client. -func (client *Client) BlobOperations(pathRenameMode *PathRenameMode) BlobOperations { - return &blobOperations{Client: client, pathRenameMode: pathRenameMode} +func (client *client) BlobOperations(pathRenameMode *PathRenameMode) BlobOperations { + return &blobOperations{client: client, pathRenameMode: pathRenameMode} } // PageBlobOperations returns the PageBlobOperations associated with this client. -func (client *Client) PageBlobOperations() PageBlobOperations { - return &pageBlobOperations{Client: client} +func (client *client) PageBlobOperations() PageBlobOperations { + return &pageBlobOperations{client: client} } // AppendBlobOperations returns the AppendBlobOperations associated with this client. -func (client *Client) AppendBlobOperations() AppendBlobOperations { - return &appendBlobOperations{Client: client} +func (client *client) AppendBlobOperations() AppendBlobOperations { + return &appendBlobOperations{client: client} } // BlockBlobOperations returns the BlockBlobOperations associated with this client. -func (client *Client) BlockBlobOperations() BlockBlobOperations { - return &blockBlobOperations{Client: client} +func (client *client) BlockBlobOperations() BlockBlobOperations { + return &blockBlobOperations{client: client} } diff --git a/sdk/storage/blob/2019-07-07/azblob/container.go b/sdk/storage/blob/2019-07-07/azblob/container.go index c36c5175a327..d826ff6d77ff 100644 --- a/sdk/storage/blob/2019-07-07/azblob/container.go +++ b/sdk/storage/blob/2019-07-07/azblob/container.go @@ -20,43 +20,43 @@ import ( // ContainerOperations contains the methods for the Container group. type ContainerOperations interface { // 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 - AcquireLease(ctx context.Context, options *ContainerAcquireLeaseOptions) (*ContainerAcquireLeaseResponse, error) + AcquireLease(ctx context.Context, containerAcquireLeaseOptions *ContainerAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerAcquireLeaseResponse, error) // 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 - BreakLease(ctx context.Context, options *ContainerBreakLeaseOptions) (*ContainerBreakLeaseResponse, error) + BreakLease(ctx context.Context, containerBreakLeaseOptions *ContainerBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerBreakLeaseResponse, error) // 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 - ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, options *ContainerChangeLeaseOptions) (*ContainerChangeLeaseResponse, error) + ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, containerChangeLeaseOptions *ContainerChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerChangeLeaseResponse, error) // Create - creates a new container under the specified account. If the container with the same name already exists, the operation fails - Create(ctx context.Context, options *ContainerCreateOptions) (*ContainerCreateResponse, error) + Create(ctx context.Context, containerCreateOptions *ContainerCreateOptions, containerCpkScopeInfo *ContainerCpkScopeInfo) (*ContainerCreateResponse, error) // Delete - operation marks the specified container for deletion. The container and any blobs contained within it are later deleted during garbage collection - Delete(ctx context.Context, options *ContainerDeleteOptions) (*ContainerDeleteResponse, error) + Delete(ctx context.Context, containerDeleteOptions *ContainerDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerDeleteResponse, error) // GetAccessPolicy - gets the permissions for the specified container. The permissions indicate whether container data may be accessed publicly. - GetAccessPolicy(ctx context.Context, options *ContainerGetAccessPolicyOptions) (*SignedIDentifierArrayResponse, error) + GetAccessPolicy(ctx context.Context, containerGetAccessPolicyOptions *ContainerGetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (*SignedIDentifierArrayResponse, error) // GetAccountInfo - Returns the sku name and account kind GetAccountInfo(ctx context.Context) (*ContainerGetAccountInfoResponse, error) // 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 - GetProperties(ctx context.Context, options *ContainerGetPropertiesOptions) (*ContainerGetPropertiesResponse, error) + GetProperties(ctx context.Context, containerGetPropertiesOptions *ContainerGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (*ContainerGetPropertiesResponse, error) // ListBlobFlatSegment - [Update] The List Blobs operation returns a list of the blobs under the specified container - ListBlobFlatSegment(options *ContainerListBlobFlatSegmentOptions) (ListBlobsFlatSegmentResponsePager, error) + ListBlobFlatSegment(containerListBlobFlatSegmentOptions *ContainerListBlobFlatSegmentOptions) (ListBlobsFlatSegmentResponsePager, error) // ListBlobHierarchySegment - [Update] The List Blobs operation returns a list of the blobs under the specified container - ListBlobHierarchySegment(delimiter string, options *ContainerListBlobHierarchySegmentOptions) (ListBlobsHierarchySegmentResponsePager, error) + ListBlobHierarchySegment(delimiter string, containerListBlobHierarchySegmentOptions *ContainerListBlobHierarchySegmentOptions) (ListBlobsHierarchySegmentResponsePager, error) // 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 - ReleaseLease(ctx context.Context, leaseId string, options *ContainerReleaseLeaseOptions) (*ContainerReleaseLeaseResponse, error) + ReleaseLease(ctx context.Context, leaseId string, containerReleaseLeaseOptions *ContainerReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerReleaseLeaseResponse, error) // 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 - RenewLease(ctx context.Context, leaseId string, options *ContainerRenewLeaseOptions) (*ContainerRenewLeaseResponse, error) + RenewLease(ctx context.Context, leaseId string, containerRenewLeaseOptions *ContainerRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerRenewLeaseResponse, error) // SetAccessPolicy - sets the permissions for the specified container. The permissions indicate whether blobs in a container may be accessed publicly. - SetAccessPolicy(ctx context.Context, options *ContainerSetAccessPolicyOptions) (*ContainerSetAccessPolicyResponse, error) + SetAccessPolicy(ctx context.Context, containerSetAccessPolicyOptions *ContainerSetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerSetAccessPolicyResponse, error) // SetMetadata - operation sets one or more user-defined name-value pairs for the specified container. - SetMetadata(ctx context.Context, options *ContainerSetMetadataOptions) (*ContainerSetMetadataResponse, error) + SetMetadata(ctx context.Context, containerSetMetadataOptions *ContainerSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerSetMetadataResponse, error) } // containerOperations implements the ContainerOperations interface. type containerOperations struct { - *Client + *client } // 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 -func (client *containerOperations) AcquireLease(ctx context.Context, options *ContainerAcquireLeaseOptions) (*ContainerAcquireLeaseResponse, error) { - req, err := client.acquireLeaseCreateRequest(options) +func (client *containerOperations) AcquireLease(ctx context.Context, containerAcquireLeaseOptions *ContainerAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerAcquireLeaseResponse, error) { + req, err := client.acquireLeaseCreateRequest(containerAcquireLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -72,32 +72,33 @@ func (client *containerOperations) AcquireLease(ctx context.Context, options *Co } // acquireLeaseCreateRequest creates the AcquireLease request. -func (client *containerOperations) acquireLeaseCreateRequest(options *ContainerAcquireLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) acquireLeaseCreateRequest(containerAcquireLeaseOptions *ContainerAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerAcquireLeaseOptions != nil && containerAcquireLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerAcquireLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "acquire") - if options != nil && options.Duration != nil { - req.Header.Set("x-ms-lease-duration", strconv.FormatInt(int64(*options.Duration), 10)) + if containerAcquireLeaseOptions != nil && containerAcquireLeaseOptions.Duration != nil { + req.Header.Set("x-ms-lease-duration", strconv.FormatInt(int64(*containerAcquireLeaseOptions.Duration), 10)) } - if options != nil && options.ProposedLeaseId != nil { - req.Header.Set("x-ms-proposed-lease-id", *options.ProposedLeaseId) + if containerAcquireLeaseOptions != nil && containerAcquireLeaseOptions.ProposedLeaseId != nil { + req.Header.Set("x-ms-proposed-lease-id", *containerAcquireLeaseOptions.ProposedLeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerAcquireLeaseOptions != nil && containerAcquireLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerAcquireLeaseOptions.RequestId) } return req, nil } @@ -105,7 +106,7 @@ func (client *containerOperations) acquireLeaseCreateRequest(options *ContainerA // acquireLeaseHandleResponse handles the AcquireLease response. func (client *containerOperations) acquireLeaseHandleResponse(resp *azcore.Response) (*ContainerAcquireLeaseResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.acquireLeaseHandleError(resp) } result := ContainerAcquireLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -140,9 +141,18 @@ func (client *containerOperations) acquireLeaseHandleResponse(resp *azcore.Respo return &result, nil } +// acquireLeaseHandleError handles the AcquireLease error response. +func (client *containerOperations) acquireLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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 -func (client *containerOperations) BreakLease(ctx context.Context, options *ContainerBreakLeaseOptions) (*ContainerBreakLeaseResponse, error) { - req, err := client.breakLeaseCreateRequest(options) +func (client *containerOperations) BreakLease(ctx context.Context, containerBreakLeaseOptions *ContainerBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerBreakLeaseResponse, error) { + req, err := client.breakLeaseCreateRequest(containerBreakLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -158,29 +168,30 @@ func (client *containerOperations) BreakLease(ctx context.Context, options *Cont } // breakLeaseCreateRequest creates the BreakLease request. -func (client *containerOperations) breakLeaseCreateRequest(options *ContainerBreakLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) breakLeaseCreateRequest(containerBreakLeaseOptions *ContainerBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerBreakLeaseOptions != nil && containerBreakLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerBreakLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "break") - if options != nil && options.BreakPeriod != nil { - req.Header.Set("x-ms-lease-break-period", strconv.FormatInt(int64(*options.BreakPeriod), 10)) + if containerBreakLeaseOptions != nil && containerBreakLeaseOptions.BreakPeriod != nil { + req.Header.Set("x-ms-lease-break-period", strconv.FormatInt(int64(*containerBreakLeaseOptions.BreakPeriod), 10)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerBreakLeaseOptions != nil && containerBreakLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerBreakLeaseOptions.RequestId) } return req, nil } @@ -188,7 +199,7 @@ func (client *containerOperations) breakLeaseCreateRequest(options *ContainerBre // breakLeaseHandleResponse handles the BreakLease response. func (client *containerOperations) breakLeaseHandleResponse(resp *azcore.Response) (*ContainerBreakLeaseResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.breakLeaseHandleError(resp) } result := ContainerBreakLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -228,9 +239,18 @@ func (client *containerOperations) breakLeaseHandleResponse(resp *azcore.Respons return &result, nil } +// breakLeaseHandleError handles the BreakLease error response. +func (client *containerOperations) breakLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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 -func (client *containerOperations) ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, options *ContainerChangeLeaseOptions) (*ContainerChangeLeaseResponse, error) { - req, err := client.changeLeaseCreateRequest(leaseId, proposedLeaseId, options) +func (client *containerOperations) ChangeLease(ctx context.Context, leaseId string, proposedLeaseId string, containerChangeLeaseOptions *ContainerChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerChangeLeaseResponse, error) { + req, err := client.changeLeaseCreateRequest(leaseId, proposedLeaseId, containerChangeLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -246,28 +266,29 @@ func (client *containerOperations) ChangeLease(ctx context.Context, leaseId stri } // changeLeaseCreateRequest creates the ChangeLease request. -func (client *containerOperations) changeLeaseCreateRequest(leaseId string, proposedLeaseId string, options *ContainerChangeLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) changeLeaseCreateRequest(leaseId string, proposedLeaseId string, containerChangeLeaseOptions *ContainerChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerChangeLeaseOptions != nil && containerChangeLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerChangeLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "change") req.Header.Set("x-ms-lease-id", leaseId) req.Header.Set("x-ms-proposed-lease-id", proposedLeaseId) - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerChangeLeaseOptions != nil && containerChangeLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerChangeLeaseOptions.RequestId) } return req, nil } @@ -275,7 +296,7 @@ func (client *containerOperations) changeLeaseCreateRequest(leaseId string, prop // changeLeaseHandleResponse handles the ChangeLease response. func (client *containerOperations) changeLeaseHandleResponse(resp *azcore.Response) (*ContainerChangeLeaseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.changeLeaseHandleError(resp) } result := ContainerChangeLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -310,9 +331,18 @@ func (client *containerOperations) changeLeaseHandleResponse(resp *azcore.Respon return &result, nil } +// changeLeaseHandleError handles the ChangeLease error response. +func (client *containerOperations) changeLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Create - creates a new container under the specified account. If the container with the same name already exists, the operation fails -func (client *containerOperations) Create(ctx context.Context, options *ContainerCreateOptions) (*ContainerCreateResponse, error) { - req, err := client.createCreateRequest(options) +func (client *containerOperations) Create(ctx context.Context, containerCreateOptions *ContainerCreateOptions, containerCpkScopeInfo *ContainerCpkScopeInfo) (*ContainerCreateResponse, error) { + req, err := client.createCreateRequest(containerCreateOptions, containerCpkScopeInfo) if err != nil { return nil, err } @@ -328,30 +358,33 @@ func (client *containerOperations) Create(ctx context.Context, options *Containe } // createCreateRequest creates the Create request. -func (client *containerOperations) createCreateRequest(options *ContainerCreateOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) createCreateRequest(containerCreateOptions *ContainerCreateOptions, containerCpkScopeInfo *ContainerCpkScopeInfo) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerCreateOptions != nil && containerCreateOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerCreateOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if containerCreateOptions != nil && containerCreateOptions.Metadata != nil { + for k, v := range *containerCreateOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.Access != nil { - req.Header.Set("x-ms-blob-public-access", string(*options.Access)) + if containerCreateOptions != nil && containerCreateOptions.Access != nil { + req.Header.Set("x-ms-blob-public-access", string(*containerCreateOptions.Access)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerCreateOptions != nil && containerCreateOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerCreateOptions.RequestId) } - if options != nil && options.DefaultEncryptionScope != nil { - req.Header.Set("x-ms-default-encryption-scope", *options.DefaultEncryptionScope) + if containerCpkScopeInfo != nil && containerCpkScopeInfo.DefaultEncryptionScope != nil { + req.Header.Set("x-ms-default-encryption-scope", *containerCpkScopeInfo.DefaultEncryptionScope) } - if options != nil && options.PreventEncryptionScopeOverride != nil { - req.Header.Set("x-ms-deny-encryption-scope-override", strconv.FormatBool(*options.PreventEncryptionScopeOverride)) + if containerCpkScopeInfo != nil && containerCpkScopeInfo.PreventEncryptionScopeOverride != nil { + req.Header.Set("x-ms-deny-encryption-scope-override", strconv.FormatBool(*containerCpkScopeInfo.PreventEncryptionScopeOverride)) } return req, nil } @@ -359,7 +392,7 @@ func (client *containerOperations) createCreateRequest(options *ContainerCreateO // createHandleResponse handles the Create response. func (client *containerOperations) createHandleResponse(resp *azcore.Response) (*ContainerCreateResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.createHandleError(resp) } result := ContainerCreateResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -391,9 +424,18 @@ func (client *containerOperations) createHandleResponse(resp *azcore.Response) ( return &result, nil } +// createHandleError handles the Create error response. +func (client *containerOperations) createHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Delete - operation marks the specified container for deletion. The container and any blobs contained within it are later deleted during garbage collection -func (client *containerOperations) Delete(ctx context.Context, options *ContainerDeleteOptions) (*ContainerDeleteResponse, error) { - req, err := client.deleteCreateRequest(options) +func (client *containerOperations) Delete(ctx context.Context, containerDeleteOptions *ContainerDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerDeleteResponse, error) { + req, err := client.deleteCreateRequest(containerDeleteOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -409,27 +451,28 @@ func (client *containerOperations) Delete(ctx context.Context, options *Containe } // deleteCreateRequest creates the Delete request. -func (client *containerOperations) deleteCreateRequest(options *ContainerDeleteOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) deleteCreateRequest(containerDeleteOptions *ContainerDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerDeleteOptions != nil && containerDeleteOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerDeleteOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodDelete, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerDeleteOptions != nil && containerDeleteOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerDeleteOptions.RequestId) } return req, nil } @@ -437,7 +480,7 @@ func (client *containerOperations) deleteCreateRequest(options *ContainerDeleteO // deleteHandleResponse handles the Delete response. func (client *containerOperations) deleteHandleResponse(resp *azcore.Response) (*ContainerDeleteResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.deleteHandleError(resp) } result := ContainerDeleteResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -459,9 +502,18 @@ func (client *containerOperations) deleteHandleResponse(resp *azcore.Response) ( return &result, nil } +// deleteHandleError handles the Delete error response. +func (client *containerOperations) deleteHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetAccessPolicy - gets the permissions for the specified container. The permissions indicate whether container data may be accessed publicly. -func (client *containerOperations) GetAccessPolicy(ctx context.Context, options *ContainerGetAccessPolicyOptions) (*SignedIDentifierArrayResponse, error) { - req, err := client.getAccessPolicyCreateRequest(options) +func (client *containerOperations) GetAccessPolicy(ctx context.Context, containerGetAccessPolicyOptions *ContainerGetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (*SignedIDentifierArrayResponse, error) { + req, err := client.getAccessPolicyCreateRequest(containerGetAccessPolicyOptions, leaseAccessConditions) if err != nil { return nil, err } @@ -477,22 +529,23 @@ func (client *containerOperations) GetAccessPolicy(ctx context.Context, options } // getAccessPolicyCreateRequest creates the GetAccessPolicy request. -func (client *containerOperations) getAccessPolicyCreateRequest(options *ContainerGetAccessPolicyOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) getAccessPolicyCreateRequest(containerGetAccessPolicyOptions *ContainerGetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") query.Set("comp", "acl") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerGetAccessPolicyOptions != nil && containerGetAccessPolicyOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerGetAccessPolicyOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerGetAccessPolicyOptions != nil && containerGetAccessPolicyOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerGetAccessPolicyOptions.RequestId) } return req, nil } @@ -500,7 +553,7 @@ func (client *containerOperations) getAccessPolicyCreateRequest(options *Contain // getAccessPolicyHandleResponse handles the GetAccessPolicy response. func (client *containerOperations) getAccessPolicyHandleResponse(resp *azcore.Response) (*SignedIDentifierArrayResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getAccessPolicyHandleError(resp) } result := SignedIDentifierArrayResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-blob-public-access"); val != "" { @@ -535,6 +588,15 @@ func (client *containerOperations) getAccessPolicyHandleResponse(resp *azcore.Re return &result, resp.UnmarshalAsXML(&result) } +// getAccessPolicyHandleError handles the GetAccessPolicy error response. +func (client *containerOperations) getAccessPolicyHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetAccountInfo - Returns the sku name and account kind func (client *containerOperations) GetAccountInfo(ctx context.Context) (*ContainerGetAccountInfoResponse, error) { req, err := client.getAccountInfoCreateRequest() @@ -554,7 +616,8 @@ func (client *containerOperations) GetAccountInfo(ctx context.Context) (*Contain // getAccountInfoCreateRequest creates the GetAccountInfo request. func (client *containerOperations) getAccountInfoCreateRequest() (*azcore.Request, error) { - u := client.u + copy := *client.u + u := © query := u.Query() query.Set("restype", "account") query.Set("comp", "properties") @@ -567,7 +630,7 @@ func (client *containerOperations) getAccountInfoCreateRequest() (*azcore.Reques // getAccountInfoHandleResponse handles the GetAccountInfo response. func (client *containerOperations) getAccountInfoHandleResponse(resp *azcore.Response) (*ContainerGetAccountInfoResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getAccountInfoHandleError(resp) } result := ContainerGetAccountInfoResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -595,9 +658,18 @@ func (client *containerOperations) getAccountInfoHandleResponse(resp *azcore.Res return &result, nil } +// getAccountInfoHandleError handles the GetAccountInfo error response. +func (client *containerOperations) getAccountInfoHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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 -func (client *containerOperations) GetProperties(ctx context.Context, options *ContainerGetPropertiesOptions) (*ContainerGetPropertiesResponse, error) { - req, err := client.getPropertiesCreateRequest(options) +func (client *containerOperations) GetProperties(ctx context.Context, containerGetPropertiesOptions *ContainerGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (*ContainerGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(containerGetPropertiesOptions, leaseAccessConditions) if err != nil { return nil, err } @@ -613,21 +685,22 @@ func (client *containerOperations) GetProperties(ctx context.Context, options *C } // getPropertiesCreateRequest creates the GetProperties request. -func (client *containerOperations) getPropertiesCreateRequest(options *ContainerGetPropertiesOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) getPropertiesCreateRequest(containerGetPropertiesOptions *ContainerGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerGetPropertiesOptions != nil && containerGetPropertiesOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerGetPropertiesOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerGetPropertiesOptions != nil && containerGetPropertiesOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerGetPropertiesOptions.RequestId) } return req, nil } @@ -635,7 +708,7 @@ func (client *containerOperations) getPropertiesCreateRequest(options *Container // getPropertiesHandleResponse handles the GetProperties response. func (client *containerOperations) getPropertiesHandleResponse(resp *azcore.Response) (*ContainerGetPropertiesResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getPropertiesHandleError(resp) } result := ContainerGetPropertiesResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-meta"); val != "" { @@ -706,14 +779,23 @@ func (client *containerOperations) getPropertiesHandleResponse(resp *azcore.Resp return &result, nil } +// getPropertiesHandleError handles the GetProperties error response. +func (client *containerOperations) getPropertiesHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // ListBlobFlatSegment - [Update] The List Blobs operation returns a list of the blobs under the specified container -func (client *containerOperations) ListBlobFlatSegment(options *ContainerListBlobFlatSegmentOptions) (ListBlobsFlatSegmentResponsePager, error) { - req, err := client.listBlobFlatSegmentCreateRequest(options) +func (client *containerOperations) ListBlobFlatSegment(containerListBlobFlatSegmentOptions *ContainerListBlobFlatSegmentOptions) (ListBlobsFlatSegmentResponsePager, error) { + req, err := client.listBlobFlatSegmentCreateRequest(containerListBlobFlatSegmentOptions) if err != nil { return nil, err } return &listBlobsFlatSegmentResponsePager{ - client: client, + pipeline: client.p, request: req, responder: client.listBlobFlatSegmentHandleResponse, advancer: func(resp *ListBlobsFlatSegmentResponseResponse) (*azcore.Request, error) { @@ -730,31 +812,32 @@ func (client *containerOperations) ListBlobFlatSegment(options *ContainerListBlo } // listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request. -func (client *containerOperations) listBlobFlatSegmentCreateRequest(options *ContainerListBlobFlatSegmentOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) listBlobFlatSegmentCreateRequest(containerListBlobFlatSegmentOptions *ContainerListBlobFlatSegmentOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") query.Set("comp", "list") - if options != nil && options.Prefix != nil { - query.Set("prefix", *options.Prefix) + if containerListBlobFlatSegmentOptions != nil && containerListBlobFlatSegmentOptions.Prefix != nil { + query.Set("prefix", *containerListBlobFlatSegmentOptions.Prefix) } - if options != nil && options.Marker != nil { - query.Set("marker", *options.Marker) + if containerListBlobFlatSegmentOptions != nil && containerListBlobFlatSegmentOptions.Marker != nil { + query.Set("marker", *containerListBlobFlatSegmentOptions.Marker) } - if options != nil && options.Maxresults != nil { - query.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + if containerListBlobFlatSegmentOptions != nil && containerListBlobFlatSegmentOptions.Maxresults != nil { + query.Set("maxresults", strconv.FormatInt(int64(*containerListBlobFlatSegmentOptions.Maxresults), 10)) } - if options != nil && options.Include != nil { - query.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(*options.Include), "[]")), ",")) + if containerListBlobFlatSegmentOptions != nil && containerListBlobFlatSegmentOptions.Include != nil { + query.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(*containerListBlobFlatSegmentOptions.Include), "[]")), ",")) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerListBlobFlatSegmentOptions != nil && containerListBlobFlatSegmentOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerListBlobFlatSegmentOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerListBlobFlatSegmentOptions != nil && containerListBlobFlatSegmentOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerListBlobFlatSegmentOptions.RequestId) } return req, nil } @@ -762,7 +845,7 @@ func (client *containerOperations) listBlobFlatSegmentCreateRequest(options *Con // listBlobFlatSegmentHandleResponse handles the ListBlobFlatSegment response. func (client *containerOperations) listBlobFlatSegmentHandleResponse(resp *azcore.Response) (*ListBlobsFlatSegmentResponseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.listBlobFlatSegmentHandleError(resp) } result := ListBlobsFlatSegmentResponseResponse{RawResponse: resp.Response} if val := resp.Header.Get("Content-Type"); val != "" { @@ -787,14 +870,23 @@ func (client *containerOperations) listBlobFlatSegmentHandleResponse(resp *azcor return &result, resp.UnmarshalAsXML(&result.EnumerationResults) } +// listBlobFlatSegmentHandleError handles the ListBlobFlatSegment error response. +func (client *containerOperations) listBlobFlatSegmentHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // ListBlobHierarchySegment - [Update] The List Blobs operation returns a list of the blobs under the specified container -func (client *containerOperations) ListBlobHierarchySegment(delimiter string, options *ContainerListBlobHierarchySegmentOptions) (ListBlobsHierarchySegmentResponsePager, error) { - req, err := client.listBlobHierarchySegmentCreateRequest(delimiter, options) +func (client *containerOperations) ListBlobHierarchySegment(delimiter string, containerListBlobHierarchySegmentOptions *ContainerListBlobHierarchySegmentOptions) (ListBlobsHierarchySegmentResponsePager, error) { + req, err := client.listBlobHierarchySegmentCreateRequest(delimiter, containerListBlobHierarchySegmentOptions) if err != nil { return nil, err } return &listBlobsHierarchySegmentResponsePager{ - client: client, + pipeline: client.p, request: req, responder: client.listBlobHierarchySegmentHandleResponse, advancer: func(resp *ListBlobsHierarchySegmentResponseResponse) (*azcore.Request, error) { @@ -811,32 +903,33 @@ func (client *containerOperations) ListBlobHierarchySegment(delimiter string, op } // listBlobHierarchySegmentCreateRequest creates the ListBlobHierarchySegment request. -func (client *containerOperations) listBlobHierarchySegmentCreateRequest(delimiter string, options *ContainerListBlobHierarchySegmentOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) listBlobHierarchySegmentCreateRequest(delimiter string, containerListBlobHierarchySegmentOptions *ContainerListBlobHierarchySegmentOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") query.Set("comp", "list") - if options != nil && options.Prefix != nil { - query.Set("prefix", *options.Prefix) + if containerListBlobHierarchySegmentOptions != nil && containerListBlobHierarchySegmentOptions.Prefix != nil { + query.Set("prefix", *containerListBlobHierarchySegmentOptions.Prefix) } query.Set("delimiter", delimiter) - if options != nil && options.Marker != nil { - query.Set("marker", *options.Marker) + if containerListBlobHierarchySegmentOptions != nil && containerListBlobHierarchySegmentOptions.Marker != nil { + query.Set("marker", *containerListBlobHierarchySegmentOptions.Marker) } - if options != nil && options.Maxresults != nil { - query.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + if containerListBlobHierarchySegmentOptions != nil && containerListBlobHierarchySegmentOptions.Maxresults != nil { + query.Set("maxresults", strconv.FormatInt(int64(*containerListBlobHierarchySegmentOptions.Maxresults), 10)) } - if options != nil && options.Include != nil { - query.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(*options.Include), "[]")), ",")) + if containerListBlobHierarchySegmentOptions != nil && containerListBlobHierarchySegmentOptions.Include != nil { + query.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(*containerListBlobHierarchySegmentOptions.Include), "[]")), ",")) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerListBlobHierarchySegmentOptions != nil && containerListBlobHierarchySegmentOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerListBlobHierarchySegmentOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerListBlobHierarchySegmentOptions != nil && containerListBlobHierarchySegmentOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerListBlobHierarchySegmentOptions.RequestId) } return req, nil } @@ -844,7 +937,7 @@ func (client *containerOperations) listBlobHierarchySegmentCreateRequest(delimit // listBlobHierarchySegmentHandleResponse handles the ListBlobHierarchySegment response. func (client *containerOperations) listBlobHierarchySegmentHandleResponse(resp *azcore.Response) (*ListBlobsHierarchySegmentResponseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.listBlobHierarchySegmentHandleError(resp) } result := ListBlobsHierarchySegmentResponseResponse{RawResponse: resp.Response} if val := resp.Header.Get("Content-Type"); val != "" { @@ -869,9 +962,18 @@ func (client *containerOperations) listBlobHierarchySegmentHandleResponse(resp * return &result, resp.UnmarshalAsXML(&result.EnumerationResults) } +// listBlobHierarchySegmentHandleError handles the ListBlobHierarchySegment error response. +func (client *containerOperations) listBlobHierarchySegmentHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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 -func (client *containerOperations) ReleaseLease(ctx context.Context, leaseId string, options *ContainerReleaseLeaseOptions) (*ContainerReleaseLeaseResponse, error) { - req, err := client.releaseLeaseCreateRequest(leaseId, options) +func (client *containerOperations) ReleaseLease(ctx context.Context, leaseId string, containerReleaseLeaseOptions *ContainerReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerReleaseLeaseResponse, error) { + req, err := client.releaseLeaseCreateRequest(leaseId, containerReleaseLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -887,27 +989,28 @@ func (client *containerOperations) ReleaseLease(ctx context.Context, leaseId str } // releaseLeaseCreateRequest creates the ReleaseLease request. -func (client *containerOperations) releaseLeaseCreateRequest(leaseId string, options *ContainerReleaseLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) releaseLeaseCreateRequest(leaseId string, containerReleaseLeaseOptions *ContainerReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerReleaseLeaseOptions != nil && containerReleaseLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerReleaseLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "release") req.Header.Set("x-ms-lease-id", leaseId) - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerReleaseLeaseOptions != nil && containerReleaseLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerReleaseLeaseOptions.RequestId) } return req, nil } @@ -915,7 +1018,7 @@ func (client *containerOperations) releaseLeaseCreateRequest(leaseId string, opt // releaseLeaseHandleResponse handles the ReleaseLease response. func (client *containerOperations) releaseLeaseHandleResponse(resp *azcore.Response) (*ContainerReleaseLeaseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.releaseLeaseHandleError(resp) } result := ContainerReleaseLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -947,9 +1050,18 @@ func (client *containerOperations) releaseLeaseHandleResponse(resp *azcore.Respo return &result, nil } +// releaseLeaseHandleError handles the ReleaseLease error response. +func (client *containerOperations) releaseLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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 -func (client *containerOperations) RenewLease(ctx context.Context, leaseId string, options *ContainerRenewLeaseOptions) (*ContainerRenewLeaseResponse, error) { - req, err := client.renewLeaseCreateRequest(leaseId, options) +func (client *containerOperations) RenewLease(ctx context.Context, leaseId string, containerRenewLeaseOptions *ContainerRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerRenewLeaseResponse, error) { + req, err := client.renewLeaseCreateRequest(leaseId, containerRenewLeaseOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -965,27 +1077,28 @@ func (client *containerOperations) RenewLease(ctx context.Context, leaseId strin } // renewLeaseCreateRequest creates the RenewLease request. -func (client *containerOperations) renewLeaseCreateRequest(leaseId string, options *ContainerRenewLeaseOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) renewLeaseCreateRequest(leaseId string, containerRenewLeaseOptions *ContainerRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "lease") query.Set("restype", "container") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerRenewLeaseOptions != nil && containerRenewLeaseOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerRenewLeaseOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-lease-action", "renew") req.Header.Set("x-ms-lease-id", leaseId) - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerRenewLeaseOptions != nil && containerRenewLeaseOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerRenewLeaseOptions.RequestId) } return req, nil } @@ -993,7 +1106,7 @@ func (client *containerOperations) renewLeaseCreateRequest(leaseId string, optio // renewLeaseHandleResponse handles the RenewLease response. func (client *containerOperations) renewLeaseHandleResponse(resp *azcore.Response) (*ContainerRenewLeaseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.renewLeaseHandleError(resp) } result := ContainerRenewLeaseResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1028,9 +1141,18 @@ func (client *containerOperations) renewLeaseHandleResponse(resp *azcore.Respons return &result, nil } +// renewLeaseHandleError handles the RenewLease error response. +func (client *containerOperations) renewLeaseHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SetAccessPolicy - sets the permissions for the specified container. The permissions indicate whether blobs in a container may be accessed publicly. -func (client *containerOperations) SetAccessPolicy(ctx context.Context, options *ContainerSetAccessPolicyOptions) (*ContainerSetAccessPolicyResponse, error) { - req, err := client.setAccessPolicyCreateRequest(options) +func (client *containerOperations) SetAccessPolicy(ctx context.Context, containerSetAccessPolicyOptions *ContainerSetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerSetAccessPolicyResponse, error) { + req, err := client.setAccessPolicyCreateRequest(containerSetAccessPolicyOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -1046,43 +1168,47 @@ func (client *containerOperations) SetAccessPolicy(ctx context.Context, options } // setAccessPolicyCreateRequest creates the SetAccessPolicy request. -func (client *containerOperations) setAccessPolicyCreateRequest(options *ContainerSetAccessPolicyOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) setAccessPolicyCreateRequest(containerSetAccessPolicyOptions *ContainerSetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") query.Set("comp", "acl") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerSetAccessPolicyOptions != nil && containerSetAccessPolicyOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerSetAccessPolicyOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.Access != nil { - req.Header.Set("x-ms-blob-public-access", string(*options.Access)) + if containerSetAccessPolicyOptions != nil && containerSetAccessPolicyOptions.Access != nil { + req.Header.Set("x-ms-blob-public-access", string(*containerSetAccessPolicyOptions.Access)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerSetAccessPolicyOptions != nil && containerSetAccessPolicyOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerSetAccessPolicyOptions.RequestId) } type wrapper struct { XMLName xml.Name `xml:"SignedIdentifiers"` ContainerAcl *[]SignedIDentifier `xml:"SignedIdentifier"` } - return req, req.MarshalAsXML(wrapper{ContainerAcl: options.ContainerAcl}) + if containerSetAccessPolicyOptions != nil { + return req, req.MarshalAsXML(wrapper{ContainerAcl: containerSetAccessPolicyOptions.ContainerAcl}) + } + return req, nil } // setAccessPolicyHandleResponse handles the SetAccessPolicy response. func (client *containerOperations) setAccessPolicyHandleResponse(resp *azcore.Response) (*ContainerSetAccessPolicyResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.setAccessPolicyHandleError(resp) } result := ContainerSetAccessPolicyResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1114,9 +1240,18 @@ func (client *containerOperations) setAccessPolicyHandleResponse(resp *azcore.Re return &result, nil } +// setAccessPolicyHandleError handles the SetAccessPolicy error response. +func (client *containerOperations) setAccessPolicyHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SetMetadata - operation sets one or more user-defined name-value pairs for the specified container. -func (client *containerOperations) SetMetadata(ctx context.Context, options *ContainerSetMetadataOptions) (*ContainerSetMetadataResponse, error) { - req, err := client.setMetadataCreateRequest(options) +func (client *containerOperations) SetMetadata(ctx context.Context, containerSetMetadataOptions *ContainerSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*ContainerSetMetadataResponse, error) { + req, err := client.setMetadataCreateRequest(containerSetMetadataOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -1132,28 +1267,31 @@ func (client *containerOperations) SetMetadata(ctx context.Context, options *Con } // setMetadataCreateRequest creates the SetMetadata request. -func (client *containerOperations) setMetadataCreateRequest(options *ContainerSetMetadataOptions) (*azcore.Request, error) { - u := client.u +func (client *containerOperations) setMetadataCreateRequest(containerSetMetadataOptions *ContainerSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "container") query.Set("comp", "metadata") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if containerSetMetadataOptions != nil && containerSetMetadataOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*containerSetMetadataOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if containerSetMetadataOptions != nil && containerSetMetadataOptions.Metadata != nil { + for k, v := range *containerSetMetadataOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if containerSetMetadataOptions != nil && containerSetMetadataOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *containerSetMetadataOptions.RequestId) } return req, nil } @@ -1161,7 +1299,7 @@ func (client *containerOperations) setMetadataCreateRequest(options *ContainerSe // setMetadataHandleResponse handles the SetMetadata response. func (client *containerOperations) setMetadataHandleResponse(resp *azcore.Response) (*ContainerSetMetadataResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.setMetadataHandleError(resp) } result := ContainerSetMetadataResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1192,3 +1330,12 @@ func (client *containerOperations) setMetadataHandleResponse(resp *azcore.Respon } return &result, nil } + +// setMetadataHandleError handles the SetMetadata error response. +func (client *containerOperations) setMetadataHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} diff --git a/sdk/storage/blob/2019-07-07/azblob/directory.go b/sdk/storage/blob/2019-07-07/azblob/directory.go index 47a0c554f8e9..a2f3c37554dc 100644 --- a/sdk/storage/blob/2019-07-07/azblob/directory.go +++ b/sdk/storage/blob/2019-07-07/azblob/directory.go @@ -16,26 +16,26 @@ import ( // DirectoryOperations contains the methods for the Directory group. type DirectoryOperations interface { // Create - Create a 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: "*". - Create(ctx context.Context, options *DirectoryCreateOptions) (*DirectoryCreateResponse, error) + Create(ctx context.Context, directoryCreateOptions *DirectoryCreateOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectoryCreateResponse, error) // Delete - Deletes the directory - Delete(ctx context.Context, recursiveDirectoryDelete bool, options *DirectoryDeleteOptions) (*DirectoryDeleteResponse, error) + Delete(ctx context.Context, recursiveDirectoryDelete bool, directoryDeleteOptions *DirectoryDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectoryDeleteResponse, error) // GetAccessControl - Get the owner, group, permissions, or access control list for a directory. - GetAccessControl(ctx context.Context, options *DirectoryGetAccessControlOptions) (*DirectoryGetAccessControlResponse, error) + GetAccessControl(ctx context.Context, directoryGetAccessControlOptions *DirectoryGetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectoryGetAccessControlResponse, error) // Rename - Rename a 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: "*". - Rename(ctx context.Context, renameSource string, options *DirectoryRenameOptions) (*DirectoryRenameResponse, error) + Rename(ctx context.Context, renameSource string, directoryRenameOptions *DirectoryRenameOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*DirectoryRenameResponse, error) // SetAccessControl - Set the owner, group, permissions, or access control list for a directory. - SetAccessControl(ctx context.Context, options *DirectorySetAccessControlOptions) (*DirectorySetAccessControlResponse, error) + SetAccessControl(ctx context.Context, directorySetAccessControlOptions *DirectorySetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectorySetAccessControlResponse, error) } // directoryOperations implements the DirectoryOperations interface. type directoryOperations struct { - *Client + *client pathRenameMode *PathRenameMode } // Create - Create a 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: "*". -func (client *directoryOperations) Create(ctx context.Context, options *DirectoryCreateOptions) (*DirectoryCreateResponse, error) { - req, err := client.createCreateRequest(options) +func (client *directoryOperations) Create(ctx context.Context, directoryCreateOptions *DirectoryCreateOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectoryCreateResponse, error) { + req, err := client.createCreateRequest(directoryCreateOptions, directoryHttpHeaders, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -51,57 +51,58 @@ func (client *directoryOperations) Create(ctx context.Context, options *Director } // createCreateRequest creates the Create request. -func (client *directoryOperations) createCreateRequest(options *DirectoryCreateOptions) (*azcore.Request, error) { - u := client.u +func (client *directoryOperations) createCreateRequest(directoryCreateOptions *DirectoryCreateOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("resource", "directory") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if directoryCreateOptions != nil && directoryCreateOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*directoryCreateOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.DirectoryProperties != nil { - req.Header.Set("x-ms-properties", *options.DirectoryProperties) + if directoryCreateOptions != nil && directoryCreateOptions.DirectoryProperties != nil { + req.Header.Set("x-ms-properties", *directoryCreateOptions.DirectoryProperties) } - if options != nil && options.PosixPermissions != nil { - req.Header.Set("x-ms-permissions", *options.PosixPermissions) + if directoryCreateOptions != nil && directoryCreateOptions.PosixPermissions != nil { + req.Header.Set("x-ms-permissions", *directoryCreateOptions.PosixPermissions) } - if options != nil && options.PosixUmask != nil { - req.Header.Set("x-ms-umask", *options.PosixUmask) + if directoryCreateOptions != nil && directoryCreateOptions.PosixUmask != nil { + req.Header.Set("x-ms-umask", *directoryCreateOptions.PosixUmask) } - if options != nil && options.CacheControl != nil { - req.Header.Set("x-ms-cache-control", *options.CacheControl) + if directoryHttpHeaders != nil && directoryHttpHeaders.CacheControl != nil { + req.Header.Set("x-ms-cache-control", *directoryHttpHeaders.CacheControl) } - if options != nil && options.ContentType != nil { - req.Header.Set("x-ms-content-type", *options.ContentType) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentType != nil { + req.Header.Set("x-ms-content-type", *directoryHttpHeaders.ContentType) } - if options != nil && options.ContentEncoding != nil { - req.Header.Set("x-ms-content-encoding", *options.ContentEncoding) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentEncoding != nil { + req.Header.Set("x-ms-content-encoding", *directoryHttpHeaders.ContentEncoding) } - if options != nil && options.ContentLanguage != nil { - req.Header.Set("x-ms-content-language", *options.ContentLanguage) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentLanguage != nil { + req.Header.Set("x-ms-content-language", *directoryHttpHeaders.ContentLanguage) } - if options != nil && options.ContentDisposition != nil { - req.Header.Set("x-ms-content-disposition", *options.ContentDisposition) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentDisposition != nil { + req.Header.Set("x-ms-content-disposition", *directoryHttpHeaders.ContentDisposition) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if directoryCreateOptions != nil && directoryCreateOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *directoryCreateOptions.RequestId) } return req, nil } @@ -109,7 +110,7 @@ func (client *directoryOperations) createCreateRequest(options *DirectoryCreateO // createHandleResponse handles the Create response. func (client *directoryOperations) createHandleResponse(resp *azcore.Response) (*DirectoryCreateResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newDataLakeStorageError(resp) + return nil, client.createHandleError(resp) } result := DirectoryCreateResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -148,9 +149,18 @@ func (client *directoryOperations) createHandleResponse(resp *azcore.Response) ( return &result, nil } +// createHandleError handles the Create error response. +func (client *directoryOperations) createHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Delete - Deletes the directory -func (client *directoryOperations) Delete(ctx context.Context, recursiveDirectoryDelete bool, options *DirectoryDeleteOptions) (*DirectoryDeleteResponse, error) { - req, err := client.deleteCreateRequest(recursiveDirectoryDelete, options) +func (client *directoryOperations) Delete(ctx context.Context, recursiveDirectoryDelete bool, directoryDeleteOptions *DirectoryDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectoryDeleteResponse, error) { + req, err := client.deleteCreateRequest(recursiveDirectoryDelete, directoryDeleteOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -166,36 +176,37 @@ func (client *directoryOperations) Delete(ctx context.Context, recursiveDirector } // deleteCreateRequest creates the Delete request. -func (client *directoryOperations) deleteCreateRequest(recursiveDirectoryDelete bool, options *DirectoryDeleteOptions) (*azcore.Request, error) { - u := client.u +func (client *directoryOperations) deleteCreateRequest(recursiveDirectoryDelete bool, directoryDeleteOptions *DirectoryDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if directoryDeleteOptions != nil && directoryDeleteOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*directoryDeleteOptions.Timeout), 10)) } query.Set("recursive", strconv.FormatBool(recursiveDirectoryDelete)) - if options != nil && options.Marker != nil { - query.Set("continuation", *options.Marker) + if directoryDeleteOptions != nil && directoryDeleteOptions.Marker != nil { + query.Set("continuation", *directoryDeleteOptions.Marker) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodDelete, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if directoryDeleteOptions != nil && directoryDeleteOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *directoryDeleteOptions.RequestId) } return req, nil } @@ -203,7 +214,7 @@ func (client *directoryOperations) deleteCreateRequest(recursiveDirectoryDelete // deleteHandleResponse handles the Delete response. func (client *directoryOperations) deleteHandleResponse(resp *azcore.Response) (*DirectoryDeleteResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newDataLakeStorageError(resp) + return nil, client.deleteHandleError(resp) } result := DirectoryDeleteResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-continuation"); val != "" { @@ -228,9 +239,18 @@ func (client *directoryOperations) deleteHandleResponse(resp *azcore.Response) ( return &result, nil } +// deleteHandleError handles the Delete error response. +func (client *directoryOperations) deleteHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetAccessControl - Get the owner, group, permissions, or access control list for a directory. -func (client *directoryOperations) GetAccessControl(ctx context.Context, options *DirectoryGetAccessControlOptions) (*DirectoryGetAccessControlResponse, error) { - req, err := client.getAccessControlCreateRequest(options) +func (client *directoryOperations) GetAccessControl(ctx context.Context, directoryGetAccessControlOptions *DirectoryGetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectoryGetAccessControlResponse, error) { + req, err := client.getAccessControlCreateRequest(directoryGetAccessControlOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -246,35 +266,36 @@ func (client *directoryOperations) GetAccessControl(ctx context.Context, options } // getAccessControlCreateRequest creates the GetAccessControl request. -func (client *directoryOperations) getAccessControlCreateRequest(options *DirectoryGetAccessControlOptions) (*azcore.Request, error) { - u := client.u +func (client *directoryOperations) getAccessControlCreateRequest(directoryGetAccessControlOptions *DirectoryGetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("action", "getAccessControl") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if directoryGetAccessControlOptions != nil && directoryGetAccessControlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*directoryGetAccessControlOptions.Timeout), 10)) } - if options != nil && options.Upn != nil { - query.Set("upn", strconv.FormatBool(*options.Upn)) + if directoryGetAccessControlOptions != nil && directoryGetAccessControlOptions.Upn != nil { + query.Set("upn", strconv.FormatBool(*directoryGetAccessControlOptions.Upn)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodHead, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if directoryGetAccessControlOptions != nil && directoryGetAccessControlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *directoryGetAccessControlOptions.RequestId) } req.Header.Set("x-ms-version", "2019-07-07") return req, nil @@ -283,7 +304,7 @@ func (client *directoryOperations) getAccessControlCreateRequest(options *Direct // getAccessControlHandleResponse handles the GetAccessControl response. func (client *directoryOperations) getAccessControlHandleResponse(resp *azcore.Response) (*DirectoryGetAccessControlResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newDataLakeStorageError(resp) + return nil, client.getAccessControlHandleError(resp) } result := DirectoryGetAccessControlResponse{RawResponse: resp.Response} if val := resp.Header.Get("Date"); val != "" { @@ -324,9 +345,18 @@ func (client *directoryOperations) getAccessControlHandleResponse(resp *azcore.R return &result, nil } +// getAccessControlHandleError handles the GetAccessControl error response. +func (client *directoryOperations) getAccessControlHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Rename - Rename a 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: "*". -func (client *directoryOperations) Rename(ctx context.Context, renameSource string, options *DirectoryRenameOptions) (*DirectoryRenameResponse, error) { - req, err := client.renameCreateRequest(renameSource, options) +func (client *directoryOperations) Rename(ctx context.Context, renameSource string, directoryRenameOptions *DirectoryRenameOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*DirectoryRenameResponse, error) { + req, err := client.renameCreateRequest(renameSource, directoryRenameOptions, directoryHttpHeaders, leaseAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions) if err != nil { return nil, err } @@ -342,14 +372,15 @@ func (client *directoryOperations) Rename(ctx context.Context, renameSource stri } // renameCreateRequest creates the Rename request. -func (client *directoryOperations) renameCreateRequest(renameSource string, options *DirectoryRenameOptions) (*azcore.Request, error) { - u := client.u +func (client *directoryOperations) renameCreateRequest(renameSource string, directoryRenameOptions *DirectoryRenameOptions, directoryHttpHeaders *DirectoryHttpHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if directoryRenameOptions != nil && directoryRenameOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*directoryRenameOptions.Timeout), 10)) } - if options != nil && options.Marker != nil { - query.Set("continuation", *options.Marker) + if directoryRenameOptions != nil && directoryRenameOptions.Marker != nil { + query.Set("continuation", *directoryRenameOptions.Marker) } if client.pathRenameMode != nil { query.Set("mode", string(*client.pathRenameMode)) @@ -357,63 +388,63 @@ func (client *directoryOperations) renameCreateRequest(renameSource string, opti u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-rename-source", renameSource) - if options != nil && options.DirectoryProperties != nil { - req.Header.Set("x-ms-properties", *options.DirectoryProperties) + if directoryRenameOptions != nil && directoryRenameOptions.DirectoryProperties != nil { + req.Header.Set("x-ms-properties", *directoryRenameOptions.DirectoryProperties) } - if options != nil && options.PosixPermissions != nil { - req.Header.Set("x-ms-permissions", *options.PosixPermissions) + if directoryRenameOptions != nil && directoryRenameOptions.PosixPermissions != nil { + req.Header.Set("x-ms-permissions", *directoryRenameOptions.PosixPermissions) } - if options != nil && options.PosixUmask != nil { - req.Header.Set("x-ms-umask", *options.PosixUmask) + if directoryRenameOptions != nil && directoryRenameOptions.PosixUmask != nil { + req.Header.Set("x-ms-umask", *directoryRenameOptions.PosixUmask) } - if options != nil && options.CacheControl != nil { - req.Header.Set("x-ms-cache-control", *options.CacheControl) + if directoryHttpHeaders != nil && directoryHttpHeaders.CacheControl != nil { + req.Header.Set("x-ms-cache-control", *directoryHttpHeaders.CacheControl) } - if options != nil && options.ContentType != nil { - req.Header.Set("x-ms-content-type", *options.ContentType) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentType != nil { + req.Header.Set("x-ms-content-type", *directoryHttpHeaders.ContentType) } - if options != nil && options.ContentEncoding != nil { - req.Header.Set("x-ms-content-encoding", *options.ContentEncoding) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentEncoding != nil { + req.Header.Set("x-ms-content-encoding", *directoryHttpHeaders.ContentEncoding) } - if options != nil && options.ContentLanguage != nil { - req.Header.Set("x-ms-content-language", *options.ContentLanguage) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentLanguage != nil { + req.Header.Set("x-ms-content-language", *directoryHttpHeaders.ContentLanguage) } - if options != nil && options.ContentDisposition != nil { - req.Header.Set("x-ms-content-disposition", *options.ContentDisposition) + if directoryHttpHeaders != nil && directoryHttpHeaders.ContentDisposition != nil { + req.Header.Set("x-ms-content-disposition", *directoryHttpHeaders.ContentDisposition) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.SourceLeaseId != nil { - req.Header.Set("x-ms-source-lease-id", *options.SourceLeaseId) + if directoryRenameOptions != nil && directoryRenameOptions.SourceLeaseId != nil { + req.Header.Set("x-ms-source-lease-id", *directoryRenameOptions.SourceLeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.SourceIfModifiedSince != nil { - req.Header.Set("x-ms-source-if-modified-since", options.SourceIfModifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Header.Set("x-ms-source-if-modified-since", sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfUnmodifiedSince != nil { - req.Header.Set("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Header.Set("x-ms-source-if-unmodified-since", sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfMatch != nil { - req.Header.Set("x-ms-source-if-match", *options.SourceIfMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Header.Set("x-ms-source-if-match", *sourceModifiedAccessConditions.SourceIfMatch) } - if options != nil && options.SourceIfNoneMatch != nil { - req.Header.Set("x-ms-source-if-none-match", *options.SourceIfNoneMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Header.Set("x-ms-source-if-none-match", *sourceModifiedAccessConditions.SourceIfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if directoryRenameOptions != nil && directoryRenameOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *directoryRenameOptions.RequestId) } return req, nil } @@ -421,7 +452,7 @@ func (client *directoryOperations) renameCreateRequest(renameSource string, opti // renameHandleResponse handles the Rename response. func (client *directoryOperations) renameHandleResponse(resp *azcore.Response) (*DirectoryRenameResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newDataLakeStorageError(resp) + return nil, client.renameHandleError(resp) } result := DirectoryRenameResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-continuation"); val != "" { @@ -463,9 +494,18 @@ func (client *directoryOperations) renameHandleResponse(resp *azcore.Response) ( return &result, nil } +// renameHandleError handles the Rename error response. +func (client *directoryOperations) renameHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SetAccessControl - Set the owner, group, permissions, or access control list for a directory. -func (client *directoryOperations) SetAccessControl(ctx context.Context, options *DirectorySetAccessControlOptions) (*DirectorySetAccessControlResponse, error) { - req, err := client.setAccessControlCreateRequest(options) +func (client *directoryOperations) SetAccessControl(ctx context.Context, directorySetAccessControlOptions *DirectorySetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*DirectorySetAccessControlResponse, error) { + req, err := client.setAccessControlCreateRequest(directorySetAccessControlOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -481,44 +521,45 @@ func (client *directoryOperations) SetAccessControl(ctx context.Context, options } // setAccessControlCreateRequest creates the SetAccessControl request. -func (client *directoryOperations) setAccessControlCreateRequest(options *DirectorySetAccessControlOptions) (*azcore.Request, error) { - u := client.u +func (client *directoryOperations) setAccessControlCreateRequest(directorySetAccessControlOptions *DirectorySetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("action", "setAccessControl") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if directorySetAccessControlOptions != nil && directorySetAccessControlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*directorySetAccessControlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPatch, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.Owner != nil { - req.Header.Set("x-ms-owner", *options.Owner) + if directorySetAccessControlOptions != nil && directorySetAccessControlOptions.Owner != nil { + req.Header.Set("x-ms-owner", *directorySetAccessControlOptions.Owner) } - if options != nil && options.Group != nil { - req.Header.Set("x-ms-group", *options.Group) + if directorySetAccessControlOptions != nil && directorySetAccessControlOptions.Group != nil { + req.Header.Set("x-ms-group", *directorySetAccessControlOptions.Group) } - if options != nil && options.PosixPermissions != nil { - req.Header.Set("x-ms-permissions", *options.PosixPermissions) + if directorySetAccessControlOptions != nil && directorySetAccessControlOptions.PosixPermissions != nil { + req.Header.Set("x-ms-permissions", *directorySetAccessControlOptions.PosixPermissions) } - if options != nil && options.PosixAcl != nil { - req.Header.Set("x-ms-acl", *options.PosixAcl) + if directorySetAccessControlOptions != nil && directorySetAccessControlOptions.PosixAcl != nil { + req.Header.Set("x-ms-acl", *directorySetAccessControlOptions.PosixAcl) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if directorySetAccessControlOptions != nil && directorySetAccessControlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *directorySetAccessControlOptions.RequestId) } req.Header.Set("x-ms-version", "2019-07-07") return req, nil @@ -527,7 +568,7 @@ func (client *directoryOperations) setAccessControlCreateRequest(options *Direct // setAccessControlHandleResponse handles the SetAccessControl response. func (client *directoryOperations) setAccessControlHandleResponse(resp *azcore.Response) (*DirectorySetAccessControlResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newDataLakeStorageError(resp) + return nil, client.setAccessControlHandleError(resp) } result := DirectorySetAccessControlResponse{RawResponse: resp.Response} if val := resp.Header.Get("Date"); val != "" { @@ -555,3 +596,12 @@ func (client *directoryOperations) setAccessControlHandleResponse(resp *azcore.R } return &result, nil } + +// setAccessControlHandleError handles the SetAccessControl error response. +func (client *directoryOperations) setAccessControlHandleError(resp *azcore.Response) error { + var err DataLakeStorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} diff --git a/sdk/storage/blob/2019-07-07/azblob/enums.go b/sdk/storage/blob/2019-07-07/azblob/enums.go index a0b24abdc73b..4337c71795fd 100644 --- a/sdk/storage/blob/2019-07-07/azblob/enums.go +++ b/sdk/storage/blob/2019-07-07/azblob/enums.go @@ -25,7 +25,22 @@ const ( ) func PossibleAccessTierValues() []AccessTier { - return []AccessTier{AccessTierArchive, AccessTierCool, AccessTierHot, AccessTierP10, AccessTierP15, AccessTierP20, AccessTierP30, AccessTierP4, AccessTierP40, AccessTierP50, AccessTierP6, AccessTierP60, AccessTierP70, AccessTierP80} + return []AccessTier{ + AccessTierArchive, + AccessTierCool, + AccessTierHot, + AccessTierP10, + AccessTierP15, + AccessTierP20, + AccessTierP30, + AccessTierP4, + AccessTierP40, + AccessTierP50, + AccessTierP6, + AccessTierP60, + AccessTierP70, + AccessTierP80, + } } func (c AccessTier) ToPtr() *AccessTier { @@ -35,13 +50,21 @@ func (c AccessTier) ToPtr() *AccessTier { type AccountKind string const ( - AccountKindStorage AccountKind = "Storage" - AccountKindBlobStorage AccountKind = "BlobStorage" - AccountKindStorageV2 AccountKind = "StorageV2" + AccountKindStorage AccountKind = "Storage" + AccountKindBlobStorage AccountKind = "BlobStorage" + AccountKindStorageV2 AccountKind = "StorageV2" + AccountKindFileStorage AccountKind = "FileStorage" + AccountKindBlockBlobStorage AccountKind = "BlockBlobStorage" ) func PossibleAccountKindValues() []AccountKind { - return []AccountKind{AccountKindStorage, AccountKindBlobStorage, AccountKindStorageV2} + return []AccountKind{ + AccountKindStorage, + AccountKindBlobStorage, + AccountKindStorageV2, + AccountKindFileStorage, + AccountKindBlockBlobStorage, + } } func (c AccountKind) ToPtr() *AccountKind { @@ -56,7 +79,10 @@ const ( ) func PossibleArchiveStatusValues() []ArchiveStatus { - return []ArchiveStatus{ArchiveStatusRehydratePendingToCool, ArchiveStatusRehydratePendingToHot} + return []ArchiveStatus{ + ArchiveStatusRehydratePendingToCool, + ArchiveStatusRehydratePendingToHot, + } } func (c ArchiveStatus) ToPtr() *ArchiveStatus { @@ -72,7 +98,11 @@ const ( ) func PossibleBlobTypeValues() []BlobType { - return []BlobType{BlobTypeBlockBlob, BlobTypePageBlob, BlobTypeAppendBlob} + return []BlobType{ + BlobTypeBlockBlob, + BlobTypePageBlob, + BlobTypeAppendBlob, + } } func (c BlobType) ToPtr() *BlobType { @@ -88,7 +118,11 @@ const ( ) func PossibleBlockListTypeValues() []BlockListType { - return []BlockListType{BlockListTypeCommitted, BlockListTypeUncommitted, BlockListTypeAll} + return []BlockListType{ + BlockListTypeCommitted, + BlockListTypeUncommitted, + BlockListTypeAll, + } } func (c BlockListType) ToPtr() *BlockListType { @@ -105,7 +139,12 @@ const ( ) func PossibleCopyStatusTypeValues() []CopyStatusType { - return []CopyStatusType{CopyStatusTypePending, CopyStatusTypeSuccess, CopyStatusTypeAborted, CopyStatusTypeFailed} + return []CopyStatusType{ + CopyStatusTypePending, + CopyStatusTypeSuccess, + CopyStatusTypeAborted, + CopyStatusTypeFailed, + } } func (c CopyStatusType) ToPtr() *CopyStatusType { @@ -120,7 +159,10 @@ const ( ) func PossibleDeleteSnapshotsOptionTypeValues() []DeleteSnapshotsOptionType { - return []DeleteSnapshotsOptionType{DeleteSnapshotsOptionTypeInclude, DeleteSnapshotsOptionTypeOnly} + return []DeleteSnapshotsOptionType{ + DeleteSnapshotsOptionTypeInclude, + DeleteSnapshotsOptionTypeOnly, + } } func (c DeleteSnapshotsOptionType) ToPtr() *DeleteSnapshotsOptionType { @@ -137,7 +179,11 @@ const ( ) func PossibleGeoReplicationStatusTypeValues() []GeoReplicationStatusType { - return []GeoReplicationStatusType{GeoReplicationStatusTypeBootstrap, GeoReplicationStatusTypeLive, GeoReplicationStatusTypeUnavailable} + return []GeoReplicationStatusType{ + GeoReplicationStatusTypeBootstrap, + GeoReplicationStatusTypeLive, + GeoReplicationStatusTypeUnavailable, + } } func (c GeoReplicationStatusType) ToPtr() *GeoReplicationStatusType { @@ -152,7 +198,10 @@ const ( ) func PossibleLeaseDurationTypeValues() []LeaseDurationType { - return []LeaseDurationType{LeaseDurationTypeInfinite, LeaseDurationTypeFixed} + return []LeaseDurationType{ + LeaseDurationTypeInfinite, + LeaseDurationTypeFixed, + } } func (c LeaseDurationType) ToPtr() *LeaseDurationType { @@ -170,7 +219,13 @@ const ( ) func PossibleLeaseStateTypeValues() []LeaseStateType { - return []LeaseStateType{LeaseStateTypeAvailable, LeaseStateTypeLeased, LeaseStateTypeExpired, LeaseStateTypeBreaking, LeaseStateTypeBroken} + return []LeaseStateType{ + LeaseStateTypeAvailable, + LeaseStateTypeLeased, + LeaseStateTypeExpired, + LeaseStateTypeBreaking, + LeaseStateTypeBroken, + } } func (c LeaseStateType) ToPtr() *LeaseStateType { @@ -185,7 +240,10 @@ const ( ) func PossibleLeaseStatusTypeValues() []LeaseStatusType { - return []LeaseStatusType{LeaseStatusTypeLocked, LeaseStatusTypeUnlocked} + return []LeaseStatusType{ + LeaseStatusTypeLocked, + LeaseStatusTypeUnlocked, + } } func (c LeaseStatusType) ToPtr() *LeaseStatusType { @@ -203,7 +261,13 @@ const ( ) func PossibleListBlobsIncludeItemValues() []ListBlobsIncludeItem { - return []ListBlobsIncludeItem{ListBlobsIncludeItemCopy, ListBlobsIncludeItemDeleted, ListBlobsIncludeItemMetadata, ListBlobsIncludeItemSnapshots, ListBlobsIncludeItemUncommittedblobs} + return []ListBlobsIncludeItem{ + ListBlobsIncludeItemCopy, + ListBlobsIncludeItemDeleted, + ListBlobsIncludeItemMetadata, + ListBlobsIncludeItemSnapshots, + ListBlobsIncludeItemUncommittedblobs, + } } func (c ListBlobsIncludeItem) ToPtr() *ListBlobsIncludeItem { @@ -218,7 +282,10 @@ const ( ) func PossiblePathRenameModeValues() []PathRenameMode { - return []PathRenameMode{PathRenameModeLegacy, PathRenameModePosix} + return []PathRenameMode{ + PathRenameModeLegacy, + PathRenameModePosix, + } } func (c PathRenameMode) ToPtr() *PathRenameMode { @@ -242,7 +309,19 @@ const ( ) func PossiblePremiumPageBlobAccessTierValues() []PremiumPageBlobAccessTier { - return []PremiumPageBlobAccessTier{PremiumPageBlobAccessTierP10, PremiumPageBlobAccessTierP15, PremiumPageBlobAccessTierP20, PremiumPageBlobAccessTierP30, PremiumPageBlobAccessTierP4, PremiumPageBlobAccessTierP40, PremiumPageBlobAccessTierP50, PremiumPageBlobAccessTierP6, PremiumPageBlobAccessTierP60, PremiumPageBlobAccessTierP70, PremiumPageBlobAccessTierP80} + return []PremiumPageBlobAccessTier{ + PremiumPageBlobAccessTierP10, + PremiumPageBlobAccessTierP15, + PremiumPageBlobAccessTierP20, + PremiumPageBlobAccessTierP30, + PremiumPageBlobAccessTierP4, + PremiumPageBlobAccessTierP40, + PremiumPageBlobAccessTierP50, + PremiumPageBlobAccessTierP6, + PremiumPageBlobAccessTierP60, + PremiumPageBlobAccessTierP70, + PremiumPageBlobAccessTierP80, + } } func (c PremiumPageBlobAccessTier) ToPtr() *PremiumPageBlobAccessTier { @@ -257,7 +336,10 @@ const ( ) func PossiblePublicAccessTypeValues() []PublicAccessType { - return []PublicAccessType{PublicAccessTypeBlob, PublicAccessTypeContainer} + return []PublicAccessType{ + PublicAccessTypeBlob, + PublicAccessTypeContainer, + } } func (c PublicAccessType) ToPtr() *PublicAccessType { @@ -272,7 +354,10 @@ const ( ) func PossibleRehydratePriorityValues() []RehydratePriority { - return []RehydratePriority{RehydratePriorityHigh, RehydratePriorityStandard} + return []RehydratePriority{ + RehydratePriorityHigh, + RehydratePriorityStandard, + } } func (c RehydratePriority) ToPtr() *RehydratePriority { @@ -288,7 +373,11 @@ const ( ) func PossibleSequenceNumberActionTypeValues() []SequenceNumberActionType { - return []SequenceNumberActionType{SequenceNumberActionTypeMax, SequenceNumberActionTypeUpdate, SequenceNumberActionTypeIncrement} + return []SequenceNumberActionType{ + SequenceNumberActionTypeMax, + SequenceNumberActionTypeUpdate, + SequenceNumberActionTypeIncrement, + } } func (c SequenceNumberActionType) ToPtr() *SequenceNumberActionType { @@ -306,7 +395,13 @@ const ( ) func PossibleSkuNameValues() []SkuName { - return []SkuName{SkuNameStandardLrs, SkuNameStandardGrs, SkuNameStandardRagrs, SkuNameStandardZrs, SkuNamePremiumLrs} + return []SkuName{ + SkuNameStandardLrs, + SkuNameStandardGrs, + SkuNameStandardRagrs, + SkuNameStandardZrs, + SkuNamePremiumLrs, + } } func (c SkuName) ToPtr() *SkuName { @@ -431,7 +526,119 @@ const ( ) func PossibleStorageErrorCodeValues() []StorageErrorCode { - return []StorageErrorCode{StorageErrorCodeAccountAlreadyExists, StorageErrorCodeAccountBeingCreated, StorageErrorCodeAccountIsDisabled, StorageErrorCodeAppendPositionConditionNotMet, StorageErrorCodeAuthenticationFailed, StorageErrorCodeAuthorizationFailure, StorageErrorCodeAuthorizationPermissionMismatch, StorageErrorCodeAuthorizationProtocolMismatch, StorageErrorCodeAuthorizationResourceTypeMismatch, StorageErrorCodeAuthorizationServiceMismatch, StorageErrorCodeAuthorizationSourceIPMismatch, StorageErrorCodeBlobAlreadyExists, StorageErrorCodeBlobArchived, StorageErrorCodeBlobBeingRehydrated, StorageErrorCodeBlobNotArchived, StorageErrorCodeBlobNotFound, StorageErrorCodeBlobOverwritten, StorageErrorCodeBlobTierInadequateForContentLength, StorageErrorCodeBlockCountExceedsLimit, StorageErrorCodeBlockListTooLong, StorageErrorCodeCannotChangeToLowerTier, StorageErrorCodeCannotVerifyCopySource, StorageErrorCodeConditionHeadersNotSupported, StorageErrorCodeConditionNotMet, StorageErrorCodeContainerAlreadyExists, StorageErrorCodeContainerBeingDeleted, StorageErrorCodeContainerDisabled, StorageErrorCodeContainerNotFound, StorageErrorCodeContentLengthLargerThanTierLimit, StorageErrorCodeCopyAcrossAccountsNotSupported, StorageErrorCodeCopyIDMismatch, StorageErrorCodeEmptyMetadataKey, StorageErrorCodeFeatureVersionMismatch, StorageErrorCodeIncrementalCopyBlobMismatch, StorageErrorCodeIncrementalCopyOfEralierVersionSnapshotNotAllowed, 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, StorageErrorCodeMaxBlobSizeConditionNotMet, StorageErrorCodeMd5Mismatch, StorageErrorCodeMetadataTooLarge, StorageErrorCodeMissingContentLengthHeader, StorageErrorCodeMissingRequiredHeader, StorageErrorCodeMissingRequiredQueryParameter, StorageErrorCodeMissingRequiredXMLNode, StorageErrorCodeMultipleConditionHeadersNotSupported, StorageErrorCodeNoAuthenticationInformation, StorageErrorCodeNoPendingCopyOperation, StorageErrorCodeOperationNotAllowedOnIncrementalCopyBlob, StorageErrorCodeOperationTimedOut, StorageErrorCodeOutOfRangeInput, StorageErrorCodeOutOfRangeQueryParameterValue, StorageErrorCodePendingCopyOperation, StorageErrorCodePreviousSnapshotCannotBeNewer, StorageErrorCodePreviousSnapshotNotFound, StorageErrorCodePreviousSnapshotOperationNotSupported, StorageErrorCodeRequestBodyTooLarge, StorageErrorCodeRequestURLFailedToParse, StorageErrorCodeResourceAlreadyExists, StorageErrorCodeResourceNotFound, StorageErrorCodeResourceTypeMismatch, StorageErrorCodeSequenceNumberConditionNotMet, StorageErrorCodeSequenceNumberIncrementTooLarge, StorageErrorCodeServerBusy, StorageErrorCodeSnaphotOperationRateExceeded, StorageErrorCodeSnapshotCountExceeded, StorageErrorCodeSnapshotsPresent, StorageErrorCodeSourceConditionNotMet, StorageErrorCodeSystemInUse, StorageErrorCodeTargetConditionNotMet, StorageErrorCodeUnauthorizedBlobOverwrite, StorageErrorCodeUnsupportedHTTPVerb, StorageErrorCodeUnsupportedHeader, StorageErrorCodeUnsupportedQueryParameter, StorageErrorCodeUnsupportedXMLNode} + return []StorageErrorCode{ + StorageErrorCodeAccountAlreadyExists, + StorageErrorCodeAccountBeingCreated, + StorageErrorCodeAccountIsDisabled, + StorageErrorCodeAppendPositionConditionNotMet, + StorageErrorCodeAuthenticationFailed, + StorageErrorCodeAuthorizationFailure, + StorageErrorCodeAuthorizationPermissionMismatch, + StorageErrorCodeAuthorizationProtocolMismatch, + StorageErrorCodeAuthorizationResourceTypeMismatch, + StorageErrorCodeAuthorizationServiceMismatch, + StorageErrorCodeAuthorizationSourceIPMismatch, + StorageErrorCodeBlobAlreadyExists, + StorageErrorCodeBlobArchived, + StorageErrorCodeBlobBeingRehydrated, + StorageErrorCodeBlobNotArchived, + StorageErrorCodeBlobNotFound, + StorageErrorCodeBlobOverwritten, + StorageErrorCodeBlobTierInadequateForContentLength, + StorageErrorCodeBlockCountExceedsLimit, + StorageErrorCodeBlockListTooLong, + StorageErrorCodeCannotChangeToLowerTier, + StorageErrorCodeCannotVerifyCopySource, + StorageErrorCodeConditionHeadersNotSupported, + StorageErrorCodeConditionNotMet, + StorageErrorCodeContainerAlreadyExists, + StorageErrorCodeContainerBeingDeleted, + StorageErrorCodeContainerDisabled, + StorageErrorCodeContainerNotFound, + StorageErrorCodeContentLengthLargerThanTierLimit, + StorageErrorCodeCopyAcrossAccountsNotSupported, + StorageErrorCodeCopyIDMismatch, + StorageErrorCodeEmptyMetadataKey, + StorageErrorCodeFeatureVersionMismatch, + StorageErrorCodeIncrementalCopyBlobMismatch, + StorageErrorCodeIncrementalCopyOfEralierVersionSnapshotNotAllowed, + 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, + StorageErrorCodeMaxBlobSizeConditionNotMet, + StorageErrorCodeMd5Mismatch, + StorageErrorCodeMetadataTooLarge, + StorageErrorCodeMissingContentLengthHeader, + StorageErrorCodeMissingRequiredHeader, + StorageErrorCodeMissingRequiredQueryParameter, + StorageErrorCodeMissingRequiredXMLNode, + StorageErrorCodeMultipleConditionHeadersNotSupported, + StorageErrorCodeNoAuthenticationInformation, + StorageErrorCodeNoPendingCopyOperation, + StorageErrorCodeOperationNotAllowedOnIncrementalCopyBlob, + StorageErrorCodeOperationTimedOut, + StorageErrorCodeOutOfRangeInput, + StorageErrorCodeOutOfRangeQueryParameterValue, + StorageErrorCodePendingCopyOperation, + StorageErrorCodePreviousSnapshotCannotBeNewer, + StorageErrorCodePreviousSnapshotNotFound, + StorageErrorCodePreviousSnapshotOperationNotSupported, + StorageErrorCodeRequestBodyTooLarge, + StorageErrorCodeRequestURLFailedToParse, + StorageErrorCodeResourceAlreadyExists, + StorageErrorCodeResourceNotFound, + StorageErrorCodeResourceTypeMismatch, + StorageErrorCodeSequenceNumberConditionNotMet, + StorageErrorCodeSequenceNumberIncrementTooLarge, + StorageErrorCodeServerBusy, + StorageErrorCodeSnaphotOperationRateExceeded, + StorageErrorCodeSnapshotCountExceeded, + StorageErrorCodeSnapshotsPresent, + StorageErrorCodeSourceConditionNotMet, + StorageErrorCodeSystemInUse, + StorageErrorCodeTargetConditionNotMet, + StorageErrorCodeUnauthorizedBlobOverwrite, + StorageErrorCodeUnsupportedHTTPVerb, + StorageErrorCodeUnsupportedHeader, + StorageErrorCodeUnsupportedQueryParameter, + StorageErrorCodeUnsupportedXMLNode, + } } func (c StorageErrorCode) ToPtr() *StorageErrorCode { diff --git a/sdk/storage/blob/2019-07-07/azblob/examples_test.go b/sdk/storage/blob/2019-07-07/azblob/examples_test.go index 344af75d4aa6..a28057916cb2 100644 --- a/sdk/storage/blob/2019-07-07/azblob/examples_test.go +++ b/sdk/storage/blob/2019-07-07/azblob/examples_test.go @@ -76,12 +76,12 @@ func pathJoin(elem ...string) string { func ExampleContainerOperations_Create() { endpoint := pathJoin(getEndpoint(), containerName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } containerClient := client.ContainerOperations() - c, err := containerClient.Create(context.Background(), nil) + c, err := containerClient.Create(context.Background(), nil, nil) if err != nil { panic(err) } @@ -90,7 +90,7 @@ func ExampleContainerOperations_Create() { } func ExampleServiceOperations_ListContainersSegment() { - client, err := NewClient(getEndpoint(), getCredential(), nil) + client, err := newClient(getEndpoint(), getCredential(), nil) if err != nil { panic(err) } @@ -112,14 +112,14 @@ func ExampleServiceOperations_ListContainersSegment() { func ExampleBlockBlobOperations_Upload() { endpoint := pathJoin(getEndpoint(), containerName, blockBlobName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } const blockSize = 80 blobClient := client.BlockBlobOperations() body := azcore.NopCloser(bytes.NewReader(generateBlobContent(blockSize))) - b, err := blobClient.Upload(context.Background(), blockSize, body, nil) + b, err := blobClient.Upload(context.Background(), blockSize, body, nil, nil, nil, nil, nil, nil) if err != nil { panic(err) } @@ -129,12 +129,12 @@ func ExampleBlockBlobOperations_Upload() { func ExampleBlobOperations_Download() { endpoint := pathJoin(getEndpoint(), containerName, blockBlobName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } blobClient := client.BlobOperations(nil) - b, err := blobClient.Download(context.Background(), nil) + b, err := blobClient.Download(context.Background(), nil, nil, nil, nil) if err != nil { panic(err) } @@ -147,12 +147,12 @@ func ExampleBlobOperations_Download() { func ExampleAppendBlobOperations_Create() { endpoint := pathJoin(getEndpoint(), containerName, appendBlobName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } blobClient := client.AppendBlobOperations() - a, err := blobClient.Create(context.Background(), 0, nil) + a, err := blobClient.Create(context.Background(), 0, nil, nil, nil, nil, nil, nil) if err != nil { panic(err) } @@ -162,14 +162,14 @@ func ExampleAppendBlobOperations_Create() { func ExampleAppendBlobOperations_AppendBlock() { endpoint := pathJoin(getEndpoint(), containerName, appendBlobName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } blobClient := client.AppendBlobOperations() const blockSize = 80 body := azcore.NopCloser(bytes.NewReader(generateBlobContent(int(blockSize)))) - a, err := blobClient.AppendBlock(context.Background(), int64(blockSize), body, nil) + a, err := blobClient.AppendBlock(context.Background(), int64(blockSize), body, nil, nil, nil, nil, nil, nil) if err != nil { panic(err) } @@ -179,7 +179,7 @@ func ExampleAppendBlobOperations_AppendBlock() { func ExampleContainerOperations_ListBlobFlatSegment() { endpoint := pathJoin(getEndpoint(), containerName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } @@ -208,24 +208,24 @@ func ExampleContainerOperations_ListBlobFlatSegment() { func ExampleBlobOperations_Delete() { endpoint := pathJoin(getEndpoint(), containerName, blockBlobName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } blobClient := client.BlobOperations(nil) - d, err := blobClient.Delete(context.Background(), nil) + d, err := blobClient.Delete(context.Background(), nil, nil, nil) if err != nil { panic(err) } fmt.Println(d.RawResponse.StatusCode) endpoint = pathJoin(getEndpoint(), containerName, appendBlobName) - client, err = NewClient(endpoint, getCredential(), nil) + client, err = newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } blobClient = client.BlobOperations(nil) - d, err = blobClient.Delete(context.Background(), nil) + d, err = blobClient.Delete(context.Background(), nil, nil, nil) if err != nil { panic(err) } @@ -237,12 +237,12 @@ func ExampleBlobOperations_Delete() { func ExampleContainerOperations_Delete() { endpoint := pathJoin(getEndpoint(), containerName) - client, err := NewClient(endpoint, getCredential(), nil) + client, err := newClient(endpoint, getCredential(), nil) if err != nil { panic(err) } blobClient := client.ContainerOperations() - d, err := blobClient.Delete(context.Background(), nil) + d, err := blobClient.Delete(context.Background(), nil, nil, nil) if err != nil { panic(err) } diff --git a/sdk/storage/blob/2019-07-07/azblob/go.mod b/sdk/storage/blob/2019-07-07/azblob/go.mod index 5d1e15866adb..47500d9ab742 100644 --- a/sdk/storage/blob/2019-07-07/azblob/go.mod +++ b/sdk/storage/blob/2019-07-07/azblob/go.mod @@ -3,8 +3,6 @@ module github.com/Azure/azure-sdk-for-go/sdk/storage/blob/2019-07-07/azblob go 1.13 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v0.5.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.0.0-00010101000000-000000000000 + github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 ) - -replace github.com/Azure/azure-sdk-for-go/sdk/azidentity => ../../../../azidentity diff --git a/sdk/storage/blob/2019-07-07/azblob/go.sum b/sdk/storage/blob/2019-07-07/azblob/go.sum index 6637c0662c4c..ed434a24d1a2 100644 --- a/sdk/storage/blob/2019-07-07/azblob/go.sum +++ b/sdk/storage/blob/2019-07-07/azblob/go.sum @@ -1,4 +1,7 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.5.0 h1:8y3iLpYKpMGE3ADy1fZdjgkAH//+7K80J21bWU6G6wg= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.5.0/go.mod h1:UKq2za3CMGx75vfPM9tPSuTBNODR4hX1qAeb+GRoDkc= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 h1:sgOdyT1ZAW3nErwCuvlGrkeP03pTtbRBW5MGCXWGZws= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1 h1:f50d2lvCzW+yaZqWLzd1kU5808BeDBGdClUQybSzSVU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.1/go.mod h1:fBbm1JLvufiabxBiiZWThNODf8+bARgZ81aP3CEx3sg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0 h1:tBi9M7RlNXtG4USOpABQpCMbFpamTTGhN4JAHGdNGjc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.1.0/go.mod h1:uFM6RUSMUQ7u9Hbtdmlg0D7kHqCKCpPxKELbb29rTdA= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.1/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2 h1:d1hG+ChFZNyblEulXP3unkwzUmh83grtG3t4sMV+6Xg= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.2/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= diff --git a/sdk/storage/blob/2019-07-07/azblob/models.go b/sdk/storage/blob/2019-07-07/azblob/models.go index 9d3b2cdaa803..7b1225e9d409 100644 --- a/sdk/storage/blob/2019-07-07/azblob/models.go +++ b/sdk/storage/blob/2019-07-07/azblob/models.go @@ -8,7 +8,6 @@ package azblob import ( "encoding/xml" "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "net/http" "net/url" "time" @@ -26,6 +25,7 @@ type AccessPolicy struct { Start *time.Time `xml:"Start"` } +// MarshalXML implements the xml.Marshaller interface for type AccessPolicy. func (a AccessPolicy) MarshalXML(e *xml.Encoder, start xml.StartElement) error { type alias AccessPolicy aux := &struct { @@ -40,6 +40,7 @@ func (a AccessPolicy) MarshalXML(e *xml.Encoder, start xml.StartElement) error { return e.EncodeElement(aux, start) } +// UnmarshalXML implements the xml.Unmarshaller interface for type AccessPolicy. func (a *AccessPolicy) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { type alias AccessPolicy aux := &struct { @@ -59,33 +60,6 @@ func (a *AccessPolicy) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro // AppendBlobAppendBlockFromURLOptions contains the optional parameters for the AppendBlob.AppendBlockFromURL method. type AppendBlobAppendBlockFromURLOptions 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. 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string - // 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 // 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 @@ -93,14 +67,6 @@ type AppendBlobAppendBlockFromURLOptions struct { SourceContentMd5 *[]byte // Specify the crc64 calculated for the range of bytes that must be read from the copy source. SourceContentcrc64 *[]byte - // 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 // Bytes of source data in the specified range. SourceRange *string // The timeout parameter is expressed in seconds. For more information, see Setting @@ -154,33 +120,6 @@ type AppendBlobAppendBlockFromURLResponse struct { // AppendBlobAppendBlockOptions contains the optional parameters for the AppendBlob.AppendBlock method. type AppendBlobAppendBlockOptions 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. 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string - // 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 // 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 @@ -240,46 +179,12 @@ type AppendBlobAppendBlockResponse struct { // AppendBlobCreateOptions contains the optional parameters for the AppendBlob.Create method. type AppendBlobCreateOptions 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 - // 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 @@ -324,10 +229,20 @@ type AppendBlobCreateResponse struct { Version *string } +// AppendPositionAccessConditions contains a group of parameters for the AppendBlob.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 +} + // BlobAbortCopyFromURLOptions contains the optional parameters for the Blob.AbortCopyFromURL method. type BlobAbortCopyFromURLOptions struct { - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -359,14 +274,6 @@ type BlobAcquireLeaseOptions struct { // 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. Duration *int32 - // 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 // 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 @@ -413,14 +320,6 @@ type BlobBreakLeaseOptions struct { // 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 - // 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 // 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 @@ -458,14 +357,6 @@ type BlobBreakLeaseResponse struct { // BlobChangeLeaseOptions contains the optional parameters for the Blob.ChangeLease method. type BlobChangeLeaseOptions 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 // 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 @@ -503,35 +394,17 @@ type BlobChangeLeaseResponse struct { // BlobCopyFromURLOptions contains the optional parameters for the Blob.CopyFromURL method. type BlobCopyFromURLOptions 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 - // 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 // Optional. Indicates the tier to be set on the blob. Tier *AccessTier // The timeout parameter is expressed in seconds. For more information, see Setting @@ -577,31 +450,12 @@ type BlobCopyFromURLResponse struct { // BlobCreateSnapshotOptions contains the optional parameters for the Blob.CreateSnapshot method. type BlobCreateSnapshotOptions struct { - // 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 @@ -645,16 +499,6 @@ type BlobDeleteOptions 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -687,21 +531,6 @@ type BlobDeleteResponse struct { // BlobDownloadOptions contains the optional parameters for the Blob.Download method. type BlobDownloadOptions struct { - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -833,16 +662,6 @@ type BlobFlatListSegment struct { // BlobGetAccessControlOptions contains the optional parameters for the Blob.GetAccessControl method. type BlobGetAccessControlOptions 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -915,21 +734,6 @@ type BlobGetAccountInfoResponse struct { // BlobGetPropertiesOptions contains the optional parameters for the Blob.GetProperties method. type BlobGetPropertiesOptions struct { - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -1064,6 +868,25 @@ type BlobHierarchyListSegment struct { BlobPrefixes *[]BlobPrefix `xml:"BlobPrefix"` } +// BlobHttpHeaders contains a group of parameters for the Blob.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 +} + // An Azure Storage blob type BlobItem struct { Deleted *bool `xml:"Deleted"` @@ -1076,7 +899,9 @@ type BlobItem struct { } type BlobMetadata struct { - Encrypted *string `xml:"Encrypted,attr"` + // Contains additional key/value pairs not defined in the schema. + AdditionalProperties *map[string]string + Encrypted *string `xml:"Encrypted,attr"` } type BlobPrefix struct { @@ -1123,6 +948,7 @@ type BlobProperties struct { ServerEncrypted *bool `xml:"ServerEncrypted"` } +// MarshalXML implements the xml.Marshaller interface for type BlobProperties. func (b BlobProperties) MarshalXML(e *xml.Encoder, start xml.StartElement) error { type alias BlobProperties aux := &struct { @@ -1143,6 +969,7 @@ func (b BlobProperties) MarshalXML(e *xml.Encoder, start xml.StartElement) error return e.EncodeElement(aux, start) } +// UnmarshalXML implements the xml.Unmarshaller interface for type BlobProperties. func (b *BlobProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { type alias BlobProperties aux := &struct { @@ -1168,14 +995,6 @@ func (b *BlobProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) er // BlobReleaseLeaseOptions contains the optional parameters for the Blob.ReleaseLease method. type BlobReleaseLeaseOptions 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 // 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 @@ -1210,29 +1029,9 @@ type BlobReleaseLeaseResponse struct { // BlobRenameOptions contains the optional parameters for the Blob.Rename method. type BlobRenameOptions struct { - // Cache control for given resource - CacheControl *string - // Content disposition for given resource - ContentDisposition *string - // Content encoding for given resource - ContentEncoding *string - // Content language for given resource - ContentLanguage *string - // Content type for given resource - ContentType *string // Optional. User-defined properties to be stored with the file or directory, in the format of a comma-separated list of name // and value pairs "n1=v1, n2=v2, ...", where each value is base64 encoded. DirectoryProperties *string - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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. @@ -1245,15 +1044,7 @@ type BlobRenameOptions 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 - // 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 - // A lease ID for the source path. If specified, the source path must have an active lease and the leaase ID must match. + // 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. @@ -1289,14 +1080,6 @@ type BlobRenameResponse struct { // BlobRenewLeaseOptions contains the optional parameters for the Blob.RenewLease method. type BlobRenewLeaseOptions 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 // 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 @@ -1336,16 +1119,6 @@ type BlobRenewLeaseResponse struct { type BlobSetAccessControlOptions struct { // Optional. The owning group of the blob or directory. Group *string - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // Optional. The owner of the blob or directory. Owner *string // Sets POSIX access control rights on files and directories. The value is a comma-separated list of access control entries. @@ -1365,53 +1138,28 @@ type BlobSetAccessControlOptions struct { } // BlobSetAccessControlResponse contains the response from method Blob.SetAccessControl. -type BlobSetAccessControlResponse 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 - - // RawResponse contains the underlying HTTP response. - RawResponse *http.Response - - // 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 -} - -// BlobSetHTTPHeadersOptions contains the optional parameters for the Blob.SetHTTPHeaders method. -type BlobSetHTTPHeadersOptions 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string +type BlobSetAccessControlResponse 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 + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response + + // 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 +} + +// BlobSetHTTPHeadersOptions contains the optional parameters for the Blob.SetHTTPHeaders method. +type BlobSetHTTPHeadersOptions 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 @@ -1449,31 +1197,12 @@ type BlobSetHTTPHeadersResponse struct { // BlobSetMetadataOptions contains the optional parameters for the Blob.SetMetadata method. type BlobSetMetadataOptions struct { - // 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 @@ -1517,8 +1246,6 @@ type BlobSetMetadataResponse struct { // BlobSetTierOptions contains the optional parameters for the Blob.SetTier method. type BlobSetTierOptions struct { - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -1546,35 +1273,17 @@ type BlobSetTierResponse struct { // BlobStartCopyFromURLOptions contains the optional parameters for the Blob.StartCopyFromURL method. type BlobStartCopyFromURLOptions 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 - // 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 // Optional. Indicates the tier to be set on the blob. Tier *AccessTier // The timeout parameter is expressed in seconds. For more information, see Setting @@ -1651,46 +1360,12 @@ type Block struct { // BlockBlobCommitBlockListOptions contains the optional parameters for the BlockBlob.CommitBlockList method. type BlockBlobCommitBlockListOptions 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 - // 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 @@ -1746,8 +1421,6 @@ type BlockBlobCommitBlockListResponse struct { // BlockBlobGetBlockListOptions contains the optional parameters for the BlockBlob.GetBlockList method. type BlockBlobGetBlockListOptions struct { - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -1762,17 +1435,6 @@ type BlockBlobGetBlockListOptions struct { // BlockBlobStageBlockFromURLOptions contains the optional parameters for the BlockBlob.StageBlockFromURL method. type BlockBlobStageBlockFromURLOptions struct { - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -1780,14 +1442,6 @@ type BlockBlobStageBlockFromURLOptions struct { SourceContentMd5 *[]byte // Specify the crc64 calculated for the range of bytes that must be read from the copy source. SourceContentcrc64 *[]byte - // 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 // Bytes of source data in the specified range. SourceRange *string // The timeout parameter is expressed in seconds. For more information, see Setting @@ -1830,17 +1484,6 @@ type BlockBlobStageBlockFromURLResponse struct { // BlockBlobStageBlockOptions contains the optional parameters for the BlockBlob.StageBlock method. type BlockBlobStageBlockOptions struct { - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -1888,46 +1531,12 @@ type BlockBlobStageBlockResponse struct { // BlockBlobUploadOptions contains the optional parameters for the BlockBlob.Upload method. type BlockBlobUploadOptions 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 - // 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 @@ -2018,6 +1627,7 @@ type BlockLookupList struct { Uncommitted *[]string `xml:"Uncommitted"` } +// MarshalXML implements the xml.Marshaller interface for type BlockLookupList. func (b BlockLookupList) MarshalXML(e *xml.Encoder, start xml.StartElement) error { start.Name.Local = "BlockList" type alias BlockLookupList @@ -2039,10 +1649,6 @@ type ContainerAcquireLeaseOptions struct { // 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. Duration *int32 - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time // 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 @@ -2089,10 +1695,6 @@ type ContainerBreakLeaseOptions struct { // 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 - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time // 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 @@ -2130,10 +1732,6 @@ type ContainerBreakLeaseResponse struct { // ContainerChangeLeaseOptions contains the optional parameters for the Container.ChangeLease method. type ContainerChangeLeaseOptions struct { - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time // 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 @@ -2169,22 +1767,26 @@ type ContainerChangeLeaseResponse struct { Version *string } +// ContainerCpkScopeInfo contains a group of parameters for the Container.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 +} + // ContainerCreateOptions contains the optional parameters for the Container.Create method. type ContainerCreateOptions struct { // Specifies whether data in the container may be accessed publicly and the level of access Access *PublicAccessType - // 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. 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 *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 + 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 @@ -2219,12 +1821,6 @@ type ContainerCreateResponse struct { // ContainerDeleteOptions contains the optional parameters for the Container.Delete method. type ContainerDeleteOptions struct { - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -2253,8 +1849,6 @@ type ContainerDeleteResponse struct { // ContainerGetAccessPolicyOptions contains the optional parameters for the Container.GetAccessPolicy method. type ContainerGetAccessPolicyOptions struct { - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -2289,8 +1883,6 @@ type ContainerGetAccountInfoResponse struct { // ContainerGetPropertiesOptions contains the optional parameters for the Container.GetProperties method. type ContainerGetPropertiesOptions struct { - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -2353,8 +1945,8 @@ type ContainerGetPropertiesResponse struct { // An Azure Storage container type ContainerItem struct { // Dictionary of - Metadata *map[string]*string `xml:"String"` - Name *string `xml:"Name"` + Metadata *map[string]string `xml:"string"` + Name *string `xml:"Name"` // Properties of a container Properties *ContainerProperties `xml:"Properties"` @@ -2422,6 +2014,7 @@ type ContainerProperties struct { PublicAccess *PublicAccessType `xml:"PublicAccess"` } +// MarshalXML implements the xml.Marshaller interface for type ContainerProperties. func (c ContainerProperties) MarshalXML(e *xml.Encoder, start xml.StartElement) error { type alias ContainerProperties aux := &struct { @@ -2434,6 +2027,7 @@ func (c ContainerProperties) MarshalXML(e *xml.Encoder, start xml.StartElement) return e.EncodeElement(aux, start) } +// UnmarshalXML implements the xml.Unmarshaller interface for type ContainerProperties. func (c *ContainerProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { type alias ContainerProperties aux := &struct { @@ -2451,10 +2045,6 @@ func (c *ContainerProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElemen // ContainerReleaseLeaseOptions contains the optional parameters for the Container.ReleaseLease method. type ContainerReleaseLeaseOptions struct { - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time // 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 @@ -2489,10 +2079,6 @@ type ContainerReleaseLeaseResponse struct { // ContainerRenewLeaseOptions contains the optional parameters for the Container.RenewLease method. type ContainerRenewLeaseOptions struct { - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time // 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 @@ -2534,12 +2120,6 @@ type ContainerSetAccessPolicyOptions struct { Access *PublicAccessType // the acls for the container ContainerAcl *[]SignedIDentifier - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -2574,16 +2154,12 @@ type ContainerSetAccessPolicyResponse struct { // ContainerSetMetadataOptions contains the optional parameters for the Container.SetMetadata method. type ContainerSetMetadataOptions struct { - // Specify this header value to operate only on a blob if it has been modified since the specified date/time. - IfModifiedSince *time.Time - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 @@ -2639,19 +2215,32 @@ type CorsRule struct { MaxAgeInSeconds *int32 `xml:"MaxAgeInSeconds"` } +// CpkInfo contains a group of parameters for the Blob.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 *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 +} + +// CpkScopeInfo contains a group of parameters for the Blob.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 +} + type DataLakeStorageError struct { // The service error response object. DataLakeStorageErrorDetails *DataLakeStorageErrorDetails `xml:"error"` } -func newDataLakeStorageError(resp *azcore.Response) error { - err := DataLakeStorageError{} - if err := resp.UnmarshalAsXML(&err); err != nil { - return err - } - return err -} - +// Error implements the error interface for type DataLakeStorageError. func (e DataLakeStorageError) Error() string { msg := "" if e.DataLakeStorageErrorDetails != nil { @@ -2673,30 +2262,10 @@ type DataLakeStorageErrorDetails struct { } // DirectoryCreateOptions contains the optional parameters for the Directory.Create method. -type DirectoryCreateOptions struct { - // Cache control for given resource - CacheControl *string - // Content disposition for given resource - ContentDisposition *string - // Content encoding for given resource - ContentEncoding *string - // Content language for given resource - ContentLanguage *string - // Content type for given resource - ContentType *string - // Optional. User-defined properties to be stored with the file or directory, in the format of a comma-separated list of name - // and value pairs "n1=v1, n2=v2, ...", where each value is base64 encoded. - DirectoryProperties *string - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string +type DirectoryCreateOptions struct { + // Optional. User-defined properties to be stored with the file or directory, in the format of a comma-separated list of name + // and value pairs "n1=v1, n2=v2, ...", where each value is base64 encoded. + DirectoryProperties *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. @@ -2743,16 +2312,6 @@ type DirectoryCreateResponse struct { // DirectoryDeleteOptions contains the optional parameters for the Directory.Delete method. type DirectoryDeleteOptions 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // When renaming a directory, the number of paths that are renamed with each invocation is limited. If the number of paths // to be renamed 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 rename operation to continue renaming @@ -2789,16 +2348,6 @@ type DirectoryDeleteResponse struct { // DirectoryGetAccessControlOptions contains the optional parameters for the Directory.GetAccessControl method. type DirectoryGetAccessControlOptions 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -2845,8 +2394,8 @@ type DirectoryGetAccessControlResponse struct { Version *string } -// DirectoryRenameOptions contains the optional parameters for the Directory.Rename method. -type DirectoryRenameOptions struct { +// DirectoryHttpHeaders contains a group of parameters for the Directory.Create method. +type DirectoryHttpHeaders struct { // Cache control for given resource CacheControl *string // Content disposition for given resource @@ -2857,19 +2406,13 @@ type DirectoryRenameOptions struct { ContentLanguage *string // Content type for given resource ContentType *string +} + +// DirectoryRenameOptions contains the optional parameters for the Directory.Rename method. +type DirectoryRenameOptions struct { // Optional. User-defined properties to be stored with the file or directory, in the format of a comma-separated list of name // and value pairs "n1=v1, n2=v2, ...", where each value is base64 encoded. DirectoryProperties *string - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // When renaming a directory, the number of paths that are renamed with each invocation is limited. If the number of paths // to be renamed 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 rename operation to continue renaming @@ -2887,15 +2430,7 @@ type DirectoryRenameOptions 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 - // 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 - // A lease ID for the source path. If specified, the source path must have an active lease and the leaase ID must match. + // 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. @@ -2936,16 +2471,6 @@ type DirectoryRenameResponse struct { type DirectorySetAccessControlOptions struct { // Optional. The owning group of the blob or directory. Group *string - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // Optional. The owner of the blob or directory. Owner *string // Sets POSIX access control rights on files and directories. The value is a comma-separated list of access control entries. @@ -2995,6 +2520,7 @@ type GeoReplication struct { Status *GeoReplicationStatusType `xml:"Status"` } +// MarshalXML implements the xml.Marshaller interface for type GeoReplication. func (g GeoReplication) MarshalXML(e *xml.Encoder, start xml.StartElement) error { type alias GeoReplication aux := &struct { @@ -3007,6 +2533,7 @@ func (g GeoReplication) MarshalXML(e *xml.Encoder, start xml.StartElement) error return e.EncodeElement(aux, start) } +// UnmarshalXML implements the xml.Unmarshaller interface for type GeoReplication. func (g *GeoReplication) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { type alias GeoReplication aux := &struct { @@ -3031,6 +2558,12 @@ type KeyInfo struct { Start *string `xml:"Start"` } +// LeaseAccessConditions contains a group of parameters for the Container.GetProperties method. +type LeaseAccessConditions struct { + // If specified, the operation only succeeds if the resource's lease is active and matches this ID. + LeaseId *string +} + // An enumeration of blobs type ListBlobsFlatSegmentResponse struct { ContainerName *string `xml:"ContainerName,attr"` @@ -3166,33 +2699,20 @@ type Metrics struct { Version *string `xml:"Version"` } -// PageBlobClearPagesOptions contains the optional parameters for the PageBlob.ClearPages method. -type PageBlobClearPagesOptions struct { - // 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 - // 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 +// ModifiedAccessConditions contains a group of parameters for the Container.Delete 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 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 // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. IfUnmodifiedSince *time.Time - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string +} + +// PageBlobClearPagesOptions contains the optional parameters for the PageBlob.ClearPages method. +type PageBlobClearPagesOptions struct { // Return only the bytes of the blob in the specified range. RangeParameter *string // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage @@ -3238,14 +2758,6 @@ type PageBlobClearPagesResponse struct { // PageBlobCopyIncrementalOptions contains the optional parameters for the PageBlob.CopyIncremental method. type PageBlobCopyIncrementalOptions 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 // 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 @@ -3286,49 +2798,15 @@ type PageBlobCopyIncrementalResponse struct { // PageBlobCreateOptions contains the optional parameters for the PageBlob.Create method. type PageBlobCreateOptions 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 // 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. 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *string + 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 @@ -3377,16 +2855,6 @@ type PageBlobCreateResponse struct { // PageBlobGetPageRangesDiffOptions contains the optional parameters for the PageBlob.GetPageRangesDiff method. type PageBlobGetPageRangesDiffOptions 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // 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 *url.URL @@ -3411,16 +2879,6 @@ type PageBlobGetPageRangesDiffOptions struct { // PageBlobGetPageRangesOptions contains the optional parameters for the PageBlob.GetPageRanges method. type PageBlobGetPageRangesOptions 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // Return only the bytes of the blob in the specified range. RangeParameter *string // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage @@ -3437,25 +2895,6 @@ type PageBlobGetPageRangesOptions struct { // PageBlobResizeOptions contains the optional parameters for the PageBlob.Resize method. type PageBlobResizeOptions struct { - // 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 - // 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -3496,16 +2935,6 @@ type PageBlobUpdateSequenceNumberOptions 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 - // 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 - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -3543,31 +2972,6 @@ type PageBlobUpdateSequenceNumberResponse struct { // PageBlobUploadPagesFromURLOptions contains the optional parameters for the PageBlob.UploadPagesFromURL method. type PageBlobUploadPagesFromURLOptions struct { - // 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 - // 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 - // 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 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 - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *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 @@ -3575,14 +2979,6 @@ type PageBlobUploadPagesFromURLOptions struct { SourceContentMd5 *[]byte // Specify the crc64 calculated for the range of bytes that must be read from the copy source. SourceContentcrc64 *[]byte - // 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 // The timeout parameter is expressed in seconds. For more information, see Setting // Timeouts for Blob Service Operations. Timeout *int32 @@ -3629,31 +3025,6 @@ type PageBlobUploadPagesFromURLResponse struct { // PageBlobUploadPagesOptions contains the optional parameters for the PageBlob.UploadPages method. type PageBlobUploadPagesOptions struct { - // 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 - // 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 - // 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 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 - // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. - IfUnmodifiedSince *time.Time - // If specified, the operation only succeeds if the resource's lease is active and matches this ID. - LeaseId *string // Return only the bytes of the blob in the specified range. RangeParameter *string // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage @@ -3761,6 +3132,16 @@ type RetentionPolicy struct { Enabled *bool `xml:"Enabled"` } +// SequenceNumberAccessConditions contains a group of parameters for the PageBlob.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 +} + // ServiceGetAccountInfoResponse contains the response from method Service.GetAccountInfo. type ServiceGetAccountInfoResponse struct { // AccountKind contains the information returned from the x-ms-account-kind header response. @@ -3926,6 +3307,18 @@ type SignedIDentifierArrayResponse struct { Version *string `xml:"Version"` } +// SourceModifiedAccessConditions contains a group of parameters for the Directory.Rename 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 +} + // The properties that enable an account to host a static website type StaticWebsite struct { // Indicates whether this account is hosting a static website @@ -3942,14 +3335,7 @@ type StorageError struct { Message *string `xml:"Message"` } -func newStorageError(resp *azcore.Response) error { - err := StorageError{} - if err := resp.UnmarshalAsXML(&err); err != nil { - return err - } - return err -} - +// Error implements the error interface for type StorageError. func (e StorageError) Error() string { msg := "" if e.Message != nil { @@ -4055,6 +3441,7 @@ type UserDelegationKey struct { Value *string `xml:"Value"` } +// MarshalXML implements the xml.Marshaller interface for type UserDelegationKey. func (u UserDelegationKey) MarshalXML(e *xml.Encoder, start xml.StartElement) error { type alias UserDelegationKey aux := &struct { @@ -4069,6 +3456,7 @@ func (u UserDelegationKey) MarshalXML(e *xml.Encoder, start xml.StartElement) er return e.EncodeElement(aux, start) } +// UnmarshalXML implements the xml.Unmarshaller interface for type UserDelegationKey. func (u *UserDelegationKey) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { type alias UserDelegationKey aux := &struct { diff --git a/sdk/storage/blob/2019-07-07/azblob/pageblob.go b/sdk/storage/blob/2019-07-07/azblob/pageblob.go index 9da98fca6d46..64a9a971d8e4 100644 --- a/sdk/storage/blob/2019-07-07/azblob/pageblob.go +++ b/sdk/storage/blob/2019-07-07/azblob/pageblob.go @@ -18,33 +18,33 @@ import ( // PageBlobOperations contains the methods for the PageBlob group. type PageBlobOperations interface { // ClearPages - The Clear Pages operation clears a set of pages from a page blob - ClearPages(ctx context.Context, contentLength int64, options *PageBlobClearPagesOptions) (*PageBlobClearPagesResponse, error) + ClearPages(ctx context.Context, contentLength int64, pageBlobClearPagesOptions *PageBlobClearPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobClearPagesResponse, error) // 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. - CopyIncremental(ctx context.Context, copySource url.URL, options *PageBlobCopyIncrementalOptions) (*PageBlobCopyIncrementalResponse, error) + CopyIncremental(ctx context.Context, copySource url.URL, pageBlobCopyIncrementalOptions *PageBlobCopyIncrementalOptions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobCopyIncrementalResponse, error) // Create - The Create operation creates a new page blob. - Create(ctx context.Context, contentLength int64, blobContentLength int64, options *PageBlobCreateOptions) (*PageBlobCreateResponse, error) + Create(ctx context.Context, contentLength int64, blobContentLength int64, pageBlobCreateOptions *PageBlobCreateOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobCreateResponse, error) // GetPageRanges - The Get Page Ranges operation returns the list of valid page ranges for a page blob or snapshot of a page blob - GetPageRanges(ctx context.Context, options *PageBlobGetPageRangesOptions) (*PageListResponse, error) + GetPageRanges(ctx context.Context, pageBlobGetPageRangesOptions *PageBlobGetPageRangesOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageListResponse, error) // GetPageRangesDiff - 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. - GetPageRangesDiff(ctx context.Context, options *PageBlobGetPageRangesDiffOptions) (*PageListResponse, error) + GetPageRangesDiff(ctx context.Context, pageBlobGetPageRangesDiffOptions *PageBlobGetPageRangesDiffOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageListResponse, error) // Resize - Resize the Blob - Resize(ctx context.Context, blobContentLength int64, options *PageBlobResizeOptions) (*PageBlobResizeResponse, error) + Resize(ctx context.Context, blobContentLength int64, pageBlobResizeOptions *PageBlobResizeOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobResizeResponse, error) // UpdateSequenceNumber - Update the sequence number of the blob - UpdateSequenceNumber(ctx context.Context, sequenceNumberAction SequenceNumberActionType, options *PageBlobUpdateSequenceNumberOptions) (*PageBlobUpdateSequenceNumberResponse, error) + UpdateSequenceNumber(ctx context.Context, sequenceNumberAction SequenceNumberActionType, pageBlobUpdateSequenceNumberOptions *PageBlobUpdateSequenceNumberOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobUpdateSequenceNumberResponse, error) // UploadPages - The Upload Pages operation writes a range of pages to a page blob - UploadPages(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, options *PageBlobUploadPagesOptions) (*PageBlobUploadPagesResponse, error) + UploadPages(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, pageBlobUploadPagesOptions *PageBlobUploadPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobUploadPagesResponse, error) // UploadPagesFromURL - The Upload Pages operation writes a range of pages to a page blob where the contents are read from a URL - UploadPagesFromURL(ctx context.Context, sourceUrl url.URL, sourceRange string, contentLength int64, rangeParameter string, options *PageBlobUploadPagesFromURLOptions) (*PageBlobUploadPagesFromURLResponse, error) + UploadPagesFromURL(ctx context.Context, sourceUrl url.URL, sourceRange string, contentLength int64, rangeParameter string, pageBlobUploadPagesFromUrlOptions *PageBlobUploadPagesFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*PageBlobUploadPagesFromURLResponse, error) } // pageBlobOperations implements the PageBlobOperations interface. type pageBlobOperations struct { - *Client + *client } // ClearPages - The Clear Pages operation clears a set of pages from a page blob -func (client *pageBlobOperations) ClearPages(ctx context.Context, contentLength int64, options *PageBlobClearPagesOptions) (*PageBlobClearPagesResponse, error) { - req, err := client.clearPagesCreateRequest(contentLength, options) +func (client *pageBlobOperations) ClearPages(ctx context.Context, contentLength int64, pageBlobClearPagesOptions *PageBlobClearPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobClearPagesResponse, error) { + req, err := client.clearPagesCreateRequest(contentLength, pageBlobClearPagesOptions, leaseAccessConditions, cpkInfo, cpkScopeInfo, sequenceNumberAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -60,56 +60,57 @@ func (client *pageBlobOperations) ClearPages(ctx context.Context, contentLength } // clearPagesCreateRequest creates the ClearPages request. -func (client *pageBlobOperations) clearPagesCreateRequest(contentLength int64, options *PageBlobClearPagesOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) clearPagesCreateRequest(contentLength int64, pageBlobClearPagesOptions *PageBlobClearPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "page") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobClearPagesOptions != nil && pageBlobClearPagesOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobClearPagesOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-page-write", "clear") req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.RangeParameter != nil { - req.Header.Set("x-ms-range", *options.RangeParameter) + if pageBlobClearPagesOptions != nil && pageBlobClearPagesOptions.RangeParameter != nil { + req.Header.Set("x-ms-range", *pageBlobClearPagesOptions.RangeParameter) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfSequenceNumberLessThanOrEqualTo != nil { - req.Header.Set("x-ms-if-sequence-number-le", strconv.FormatInt(*options.IfSequenceNumberLessThanOrEqualTo, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo != nil { + req.Header.Set("x-ms-if-sequence-number-le", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo, 10)) } - if options != nil && options.IfSequenceNumberLessThan != nil { - req.Header.Set("x-ms-if-sequence-number-lt", strconv.FormatInt(*options.IfSequenceNumberLessThan, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThan != nil { + req.Header.Set("x-ms-if-sequence-number-lt", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThan, 10)) } - if options != nil && options.IfSequenceNumberEqualTo != nil { - req.Header.Set("x-ms-if-sequence-number-eq", strconv.FormatInt(*options.IfSequenceNumberEqualTo, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberEqualTo != nil { + req.Header.Set("x-ms-if-sequence-number-eq", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobClearPagesOptions != nil && pageBlobClearPagesOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobClearPagesOptions.RequestId) } return req, nil } @@ -117,7 +118,7 @@ func (client *pageBlobOperations) clearPagesCreateRequest(contentLength int64, o // clearPagesHandleResponse handles the ClearPages response. func (client *pageBlobOperations) clearPagesHandleResponse(resp *azcore.Response) (*PageBlobClearPagesResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.clearPagesHandleError(resp) } result := PageBlobClearPagesResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -170,9 +171,18 @@ func (client *pageBlobOperations) clearPagesHandleResponse(resp *azcore.Response return &result, nil } +// clearPagesHandleError handles the ClearPages error response. +func (client *pageBlobOperations) clearPagesHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *pageBlobOperations) CopyIncremental(ctx context.Context, copySource url.URL, options *PageBlobCopyIncrementalOptions) (*PageBlobCopyIncrementalResponse, error) { - req, err := client.copyIncrementalCreateRequest(copySource, options) +func (client *pageBlobOperations) CopyIncremental(ctx context.Context, copySource url.URL, pageBlobCopyIncrementalOptions *PageBlobCopyIncrementalOptions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobCopyIncrementalResponse, error) { + req, err := client.copyIncrementalCreateRequest(copySource, pageBlobCopyIncrementalOptions, modifiedAccessConditions) if err != nil { return nil, err } @@ -188,31 +198,32 @@ func (client *pageBlobOperations) CopyIncremental(ctx context.Context, copySourc } // copyIncrementalCreateRequest creates the CopyIncremental request. -func (client *pageBlobOperations) copyIncrementalCreateRequest(copySource url.URL, options *PageBlobCopyIncrementalOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) copyIncrementalCreateRequest(copySource url.URL, pageBlobCopyIncrementalOptions *PageBlobCopyIncrementalOptions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "incrementalcopy") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobCopyIncrementalOptions != nil && pageBlobCopyIncrementalOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobCopyIncrementalOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-copy-source", copySource.String()) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobCopyIncrementalOptions != nil && pageBlobCopyIncrementalOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobCopyIncrementalOptions.RequestId) } return req, nil } @@ -220,7 +231,7 @@ func (client *pageBlobOperations) copyIncrementalCreateRequest(copySource url.UR // copyIncrementalHandleResponse handles the CopyIncremental response. func (client *pageBlobOperations) copyIncrementalHandleResponse(resp *azcore.Response) (*PageBlobCopyIncrementalResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.copyIncrementalHandleError(resp) } result := PageBlobCopyIncrementalResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -258,9 +269,18 @@ func (client *pageBlobOperations) copyIncrementalHandleResponse(resp *azcore.Res return &result, nil } +// copyIncrementalHandleError handles the CopyIncremental error response. +func (client *pageBlobOperations) copyIncrementalHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Create - The Create operation creates a new page blob. -func (client *pageBlobOperations) Create(ctx context.Context, contentLength int64, blobContentLength int64, options *PageBlobCreateOptions) (*PageBlobCreateResponse, error) { - req, err := client.createCreateRequest(contentLength, blobContentLength, options) +func (client *pageBlobOperations) Create(ctx context.Context, contentLength int64, blobContentLength int64, pageBlobCreateOptions *PageBlobCreateOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobCreateResponse, error) { + req, err := client.createCreateRequest(contentLength, blobContentLength, pageBlobCreateOptions, blobHttpHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -276,71 +296,74 @@ func (client *pageBlobOperations) Create(ctx context.Context, contentLength int6 } // createCreateRequest creates the Create request. -func (client *pageBlobOperations) createCreateRequest(contentLength int64, blobContentLength int64, options *PageBlobCreateOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) createCreateRequest(contentLength int64, blobContentLength int64, pageBlobCreateOptions *PageBlobCreateOptions, blobHttpHeaders *BlobHttpHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobCreateOptions != nil && pageBlobCreateOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobCreateOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-blob-type", "PageBlob") req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.Tier != nil { - req.Header.Set("x-ms-access-tier", string(*options.Tier)) + if pageBlobCreateOptions != nil && pageBlobCreateOptions.Tier != nil { + req.Header.Set("x-ms-access-tier", string(*pageBlobCreateOptions.Tier)) } - if options != nil && options.BlobContentType != nil { - req.Header.Set("x-ms-blob-content-type", *options.BlobContentType) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentType != nil { + req.Header.Set("x-ms-blob-content-type", *blobHttpHeaders.BlobContentType) } - if options != nil && options.BlobContentEncoding != nil { - req.Header.Set("x-ms-blob-content-encoding", *options.BlobContentEncoding) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentEncoding != nil { + req.Header.Set("x-ms-blob-content-encoding", *blobHttpHeaders.BlobContentEncoding) } - if options != nil && options.BlobContentLanguage != nil { - req.Header.Set("x-ms-blob-content-language", *options.BlobContentLanguage) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentLanguage != nil { + req.Header.Set("x-ms-blob-content-language", *blobHttpHeaders.BlobContentLanguage) } - if options != nil && options.BlobContentMd5 != nil { - req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*options.BlobContentMd5)) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentMd5 != nil { + req.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(*blobHttpHeaders.BlobContentMd5)) } - if options != nil && options.BlobCacheControl != nil { - req.Header.Set("x-ms-blob-cache-control", *options.BlobCacheControl) + if blobHttpHeaders != nil && blobHttpHeaders.BlobCacheControl != nil { + req.Header.Set("x-ms-blob-cache-control", *blobHttpHeaders.BlobCacheControl) } - if options != nil && options.Metadata != nil { - req.Header.Set("x-ms-meta", *options.Metadata) + if pageBlobCreateOptions != nil && pageBlobCreateOptions.Metadata != nil { + for k, v := range *pageBlobCreateOptions.Metadata { + req.Header.Set("x-ms-meta-"+k, v) + } } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.BlobContentDisposition != nil { - req.Header.Set("x-ms-blob-content-disposition", *options.BlobContentDisposition) + if blobHttpHeaders != nil && blobHttpHeaders.BlobContentDisposition != nil { + req.Header.Set("x-ms-blob-content-disposition", *blobHttpHeaders.BlobContentDisposition) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-blob-content-length", strconv.FormatInt(blobContentLength, 10)) - if options != nil && options.BlobSequenceNumber != nil { - req.Header.Set("x-ms-blob-sequence-number", strconv.FormatInt(*options.BlobSequenceNumber, 10)) + if pageBlobCreateOptions != nil && pageBlobCreateOptions.BlobSequenceNumber != nil { + req.Header.Set("x-ms-blob-sequence-number", strconv.FormatInt(*pageBlobCreateOptions.BlobSequenceNumber, 10)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobCreateOptions != nil && pageBlobCreateOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobCreateOptions.RequestId) } return req, nil } @@ -348,7 +371,7 @@ func (client *pageBlobOperations) createCreateRequest(contentLength int64, blobC // createHandleResponse handles the Create response. func (client *pageBlobOperations) createHandleResponse(resp *azcore.Response) (*PageBlobCreateResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.createHandleError(resp) } result := PageBlobCreateResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -400,9 +423,18 @@ func (client *pageBlobOperations) createHandleResponse(resp *azcore.Response) (* return &result, nil } +// createHandleError handles the Create error response. +func (client *pageBlobOperations) createHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetPageRanges - The Get Page Ranges operation returns the list of valid page ranges for a page blob or snapshot of a page blob -func (client *pageBlobOperations) GetPageRanges(ctx context.Context, options *PageBlobGetPageRangesOptions) (*PageListResponse, error) { - req, err := client.getPageRangesCreateRequest(options) +func (client *pageBlobOperations) GetPageRanges(ctx context.Context, pageBlobGetPageRangesOptions *PageBlobGetPageRangesOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageListResponse, error) { + req, err := client.getPageRangesCreateRequest(pageBlobGetPageRangesOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -418,39 +450,40 @@ func (client *pageBlobOperations) GetPageRanges(ctx context.Context, options *Pa } // getPageRangesCreateRequest creates the GetPageRanges request. -func (client *pageBlobOperations) getPageRangesCreateRequest(options *PageBlobGetPageRangesOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) getPageRangesCreateRequest(pageBlobGetPageRangesOptions *PageBlobGetPageRangesOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "pagelist") - if options != nil && options.Snapshot != nil { - query.Set("snapshot", *options.Snapshot) + if pageBlobGetPageRangesOptions != nil && pageBlobGetPageRangesOptions.Snapshot != nil { + query.Set("snapshot", *pageBlobGetPageRangesOptions.Snapshot) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobGetPageRangesOptions != nil && pageBlobGetPageRangesOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobGetPageRangesOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) - if options != nil && options.RangeParameter != nil { - req.Header.Set("x-ms-range", *options.RangeParameter) + if pageBlobGetPageRangesOptions != nil && pageBlobGetPageRangesOptions.RangeParameter != nil { + req.Header.Set("x-ms-range", *pageBlobGetPageRangesOptions.RangeParameter) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobGetPageRangesOptions != nil && pageBlobGetPageRangesOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobGetPageRangesOptions.RequestId) } return req, nil } @@ -458,7 +491,7 @@ func (client *pageBlobOperations) getPageRangesCreateRequest(options *PageBlobGe // getPageRangesHandleResponse handles the GetPageRanges response. func (client *pageBlobOperations) getPageRangesHandleResponse(resp *azcore.Response) (*PageListResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getPageRangesHandleError(resp) } result := PageListResponse{RawResponse: resp.Response} if val := resp.Header.Get("Last-Modified"); val != "" { @@ -497,9 +530,18 @@ func (client *pageBlobOperations) getPageRangesHandleResponse(resp *azcore.Respo return &result, resp.UnmarshalAsXML(&result.PageList) } +// getPageRangesHandleError handles the GetPageRanges error response. +func (client *pageBlobOperations) getPageRangesHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetPageRangesDiff - 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. -func (client *pageBlobOperations) GetPageRangesDiff(ctx context.Context, options *PageBlobGetPageRangesDiffOptions) (*PageListResponse, error) { - req, err := client.getPageRangesDiffCreateRequest(options) +func (client *pageBlobOperations) GetPageRangesDiff(ctx context.Context, pageBlobGetPageRangesDiffOptions *PageBlobGetPageRangesDiffOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageListResponse, error) { + req, err := client.getPageRangesDiffCreateRequest(pageBlobGetPageRangesDiffOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -515,45 +557,46 @@ func (client *pageBlobOperations) GetPageRangesDiff(ctx context.Context, options } // getPageRangesDiffCreateRequest creates the GetPageRangesDiff request. -func (client *pageBlobOperations) getPageRangesDiffCreateRequest(options *PageBlobGetPageRangesDiffOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) getPageRangesDiffCreateRequest(pageBlobGetPageRangesDiffOptions *PageBlobGetPageRangesDiffOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "pagelist") - if options != nil && options.Snapshot != nil { - query.Set("snapshot", *options.Snapshot) + if pageBlobGetPageRangesDiffOptions != nil && pageBlobGetPageRangesDiffOptions.Snapshot != nil { + query.Set("snapshot", *pageBlobGetPageRangesDiffOptions.Snapshot) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobGetPageRangesDiffOptions != nil && pageBlobGetPageRangesDiffOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobGetPageRangesDiffOptions.Timeout), 10)) } - if options != nil && options.Prevsnapshot != nil { - query.Set("prevsnapshot", *options.Prevsnapshot) + if pageBlobGetPageRangesDiffOptions != nil && pageBlobGetPageRangesDiffOptions.Prevsnapshot != nil { + query.Set("prevsnapshot", *pageBlobGetPageRangesDiffOptions.Prevsnapshot) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) - if options != nil && options.PrevSnapshotUrl != nil { - req.Header.Set("x-ms-previous-snapshot-url", options.PrevSnapshotUrl.String()) + if pageBlobGetPageRangesDiffOptions != nil && pageBlobGetPageRangesDiffOptions.PrevSnapshotUrl != nil { + req.Header.Set("x-ms-previous-snapshot-url", pageBlobGetPageRangesDiffOptions.PrevSnapshotUrl.String()) } - if options != nil && options.RangeParameter != nil { - req.Header.Set("x-ms-range", *options.RangeParameter) + if pageBlobGetPageRangesDiffOptions != nil && pageBlobGetPageRangesDiffOptions.RangeParameter != nil { + req.Header.Set("x-ms-range", *pageBlobGetPageRangesDiffOptions.RangeParameter) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobGetPageRangesDiffOptions != nil && pageBlobGetPageRangesDiffOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobGetPageRangesDiffOptions.RequestId) } return req, nil } @@ -561,7 +604,7 @@ func (client *pageBlobOperations) getPageRangesDiffCreateRequest(options *PageBl // getPageRangesDiffHandleResponse handles the GetPageRangesDiff response. func (client *pageBlobOperations) getPageRangesDiffHandleResponse(resp *azcore.Response) (*PageListResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getPageRangesDiffHandleError(resp) } result := PageListResponse{RawResponse: resp.Response} if val := resp.Header.Get("Last-Modified"); val != "" { @@ -600,9 +643,18 @@ func (client *pageBlobOperations) getPageRangesDiffHandleResponse(resp *azcore.R return &result, resp.UnmarshalAsXML(&result.PageList) } +// getPageRangesDiffHandleError handles the GetPageRangesDiff error response. +func (client *pageBlobOperations) getPageRangesDiffHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // Resize - Resize the Blob -func (client *pageBlobOperations) Resize(ctx context.Context, blobContentLength int64, options *PageBlobResizeOptions) (*PageBlobResizeResponse, error) { - req, err := client.resizeCreateRequest(blobContentLength, options) +func (client *pageBlobOperations) Resize(ctx context.Context, blobContentLength int64, pageBlobResizeOptions *PageBlobResizeOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobResizeResponse, error) { + req, err := client.resizeCreateRequest(blobContentLength, pageBlobResizeOptions, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) if err != nil { return nil, err } @@ -618,43 +670,44 @@ func (client *pageBlobOperations) Resize(ctx context.Context, blobContentLength } // resizeCreateRequest creates the Resize request. -func (client *pageBlobOperations) resizeCreateRequest(blobContentLength int64, options *PageBlobResizeOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) resizeCreateRequest(blobContentLength int64, pageBlobResizeOptions *PageBlobResizeOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "properties") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobResizeOptions != nil && pageBlobResizeOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobResizeOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-blob-content-length", strconv.FormatInt(blobContentLength, 10)) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobResizeOptions != nil && pageBlobResizeOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobResizeOptions.RequestId) } return req, nil } @@ -662,7 +715,7 @@ func (client *pageBlobOperations) resizeCreateRequest(blobContentLength int64, o // resizeHandleResponse handles the Resize response. func (client *pageBlobOperations) resizeHandleResponse(resp *azcore.Response) (*PageBlobResizeResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.resizeHandleError(resp) } result := PageBlobResizeResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -701,9 +754,18 @@ func (client *pageBlobOperations) resizeHandleResponse(resp *azcore.Response) (* return &result, nil } +// resizeHandleError handles the Resize error response. +func (client *pageBlobOperations) resizeHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // UpdateSequenceNumber - Update the sequence number of the blob -func (client *pageBlobOperations) UpdateSequenceNumber(ctx context.Context, sequenceNumberAction SequenceNumberActionType, options *PageBlobUpdateSequenceNumberOptions) (*PageBlobUpdateSequenceNumberResponse, error) { - req, err := client.updateSequenceNumberCreateRequest(sequenceNumberAction, options) +func (client *pageBlobOperations) UpdateSequenceNumber(ctx context.Context, sequenceNumberAction SequenceNumberActionType, pageBlobUpdateSequenceNumberOptions *PageBlobUpdateSequenceNumberOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobUpdateSequenceNumberResponse, error) { + req, err := client.updateSequenceNumberCreateRequest(sequenceNumberAction, pageBlobUpdateSequenceNumberOptions, leaseAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -719,37 +781,38 @@ func (client *pageBlobOperations) UpdateSequenceNumber(ctx context.Context, sequ } // updateSequenceNumberCreateRequest creates the UpdateSequenceNumber request. -func (client *pageBlobOperations) updateSequenceNumberCreateRequest(sequenceNumberAction SequenceNumberActionType, options *PageBlobUpdateSequenceNumberOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) updateSequenceNumberCreateRequest(sequenceNumberAction SequenceNumberActionType, pageBlobUpdateSequenceNumberOptions *PageBlobUpdateSequenceNumberOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "properties") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobUpdateSequenceNumberOptions != nil && pageBlobUpdateSequenceNumberOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobUpdateSequenceNumberOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-sequence-number-action", string(sequenceNumberAction)) - if options != nil && options.BlobSequenceNumber != nil { - req.Header.Set("x-ms-blob-sequence-number", strconv.FormatInt(*options.BlobSequenceNumber, 10)) + if pageBlobUpdateSequenceNumberOptions != nil && pageBlobUpdateSequenceNumberOptions.BlobSequenceNumber != nil { + req.Header.Set("x-ms-blob-sequence-number", strconv.FormatInt(*pageBlobUpdateSequenceNumberOptions.BlobSequenceNumber, 10)) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobUpdateSequenceNumberOptions != nil && pageBlobUpdateSequenceNumberOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobUpdateSequenceNumberOptions.RequestId) } return req, nil } @@ -757,7 +820,7 @@ func (client *pageBlobOperations) updateSequenceNumberCreateRequest(sequenceNumb // updateSequenceNumberHandleResponse handles the UpdateSequenceNumber response. func (client *pageBlobOperations) updateSequenceNumberHandleResponse(resp *azcore.Response) (*PageBlobUpdateSequenceNumberResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.updateSequenceNumberHandleError(resp) } result := PageBlobUpdateSequenceNumberResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -796,9 +859,18 @@ func (client *pageBlobOperations) updateSequenceNumberHandleResponse(resp *azcor return &result, nil } +// updateSequenceNumberHandleError handles the UpdateSequenceNumber error response. +func (client *pageBlobOperations) updateSequenceNumberHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // UploadPages - The Upload Pages operation writes a range of pages to a page blob -func (client *pageBlobOperations) UploadPages(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, options *PageBlobUploadPagesOptions) (*PageBlobUploadPagesResponse, error) { - req, err := client.uploadPagesCreateRequest(contentLength, body, options) +func (client *pageBlobOperations) UploadPages(ctx context.Context, contentLength int64, body azcore.ReadSeekCloser, pageBlobUploadPagesOptions *PageBlobUploadPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*PageBlobUploadPagesResponse, error) { + req, err := client.uploadPagesCreateRequest(contentLength, body, pageBlobUploadPagesOptions, leaseAccessConditions, cpkInfo, cpkScopeInfo, sequenceNumberAccessConditions, modifiedAccessConditions) if err != nil { return nil, err } @@ -814,62 +886,63 @@ func (client *pageBlobOperations) UploadPages(ctx context.Context, contentLength } // uploadPagesCreateRequest creates the UploadPages request. -func (client *pageBlobOperations) uploadPagesCreateRequest(contentLength int64, body azcore.ReadSeekCloser, options *PageBlobUploadPagesOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) uploadPagesCreateRequest(contentLength int64, body azcore.ReadSeekCloser, pageBlobUploadPagesOptions *PageBlobUploadPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "page") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobUploadPagesOptions != nil && pageBlobUploadPagesOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobUploadPagesOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-page-write", "update") req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - if options != nil && options.TransactionalContentMd5 != nil { - req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*options.TransactionalContentMd5)) + if pageBlobUploadPagesOptions != nil && pageBlobUploadPagesOptions.TransactionalContentMd5 != nil { + req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(*pageBlobUploadPagesOptions.TransactionalContentMd5)) } - if options != nil && options.TransactionalContentCrc64 != nil { - req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*options.TransactionalContentCrc64)) + if pageBlobUploadPagesOptions != nil && pageBlobUploadPagesOptions.TransactionalContentCrc64 != nil { + req.Header.Set("x-ms-content-crc64", base64.StdEncoding.EncodeToString(*pageBlobUploadPagesOptions.TransactionalContentCrc64)) } - if options != nil && options.RangeParameter != nil { - req.Header.Set("x-ms-range", *options.RangeParameter) + if pageBlobUploadPagesOptions != nil && pageBlobUploadPagesOptions.RangeParameter != nil { + req.Header.Set("x-ms-range", *pageBlobUploadPagesOptions.RangeParameter) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.IfSequenceNumberLessThanOrEqualTo != nil { - req.Header.Set("x-ms-if-sequence-number-le", strconv.FormatInt(*options.IfSequenceNumberLessThanOrEqualTo, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo != nil { + req.Header.Set("x-ms-if-sequence-number-le", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo, 10)) } - if options != nil && options.IfSequenceNumberLessThan != nil { - req.Header.Set("x-ms-if-sequence-number-lt", strconv.FormatInt(*options.IfSequenceNumberLessThan, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThan != nil { + req.Header.Set("x-ms-if-sequence-number-lt", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThan, 10)) } - if options != nil && options.IfSequenceNumberEqualTo != nil { - req.Header.Set("x-ms-if-sequence-number-eq", strconv.FormatInt(*options.IfSequenceNumberEqualTo, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberEqualTo != nil { + req.Header.Set("x-ms-if-sequence-number-eq", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobUploadPagesOptions != nil && pageBlobUploadPagesOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobUploadPagesOptions.RequestId) } return req, req.SetBody(body) } @@ -877,7 +950,7 @@ func (client *pageBlobOperations) uploadPagesCreateRequest(contentLength int64, // uploadPagesHandleResponse handles the UploadPages response. func (client *pageBlobOperations) uploadPagesHandleResponse(resp *azcore.Response) (*PageBlobUploadPagesResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.uploadPagesHandleError(resp) } result := PageBlobUploadPagesResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -943,9 +1016,18 @@ func (client *pageBlobOperations) uploadPagesHandleResponse(resp *azcore.Respons return &result, nil } +// uploadPagesHandleError handles the UploadPages error response. +func (client *pageBlobOperations) uploadPagesHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // UploadPagesFromURL - The Upload Pages operation writes a range of pages to a page blob where the contents are read from a URL -func (client *pageBlobOperations) UploadPagesFromURL(ctx context.Context, sourceUrl url.URL, sourceRange string, contentLength int64, rangeParameter string, options *PageBlobUploadPagesFromURLOptions) (*PageBlobUploadPagesFromURLResponse, error) { - req, err := client.uploadPagesFromUrlCreateRequest(sourceUrl, sourceRange, contentLength, rangeParameter, options) +func (client *pageBlobOperations) UploadPagesFromURL(ctx context.Context, sourceUrl url.URL, sourceRange string, contentLength int64, rangeParameter string, pageBlobUploadPagesFromUrlOptions *PageBlobUploadPagesFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*PageBlobUploadPagesFromURLResponse, error) { + req, err := client.uploadPagesFromUrlCreateRequest(sourceUrl, sourceRange, contentLength, rangeParameter, pageBlobUploadPagesFromUrlOptions, cpkInfo, cpkScopeInfo, leaseAccessConditions, sequenceNumberAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions) if err != nil { return nil, err } @@ -961,74 +1043,75 @@ func (client *pageBlobOperations) UploadPagesFromURL(ctx context.Context, source } // uploadPagesFromUrlCreateRequest creates the UploadPagesFromURL request. -func (client *pageBlobOperations) uploadPagesFromUrlCreateRequest(sourceUrl url.URL, sourceRange string, contentLength int64, rangeParameter string, options *PageBlobUploadPagesFromURLOptions) (*azcore.Request, error) { - u := client.u +func (client *pageBlobOperations) uploadPagesFromUrlCreateRequest(sourceUrl url.URL, sourceRange string, contentLength int64, rangeParameter string, pageBlobUploadPagesFromUrlOptions *PageBlobUploadPagesFromURLOptions, cpkInfo *CpkInfo, cpkScopeInfo *CpkScopeInfo, leaseAccessConditions *LeaseAccessConditions, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "page") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if pageBlobUploadPagesFromUrlOptions != nil && pageBlobUploadPagesFromUrlOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*pageBlobUploadPagesFromUrlOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-page-write", "update") req.Header.Set("x-ms-copy-source", sourceUrl.String()) req.Header.Set("x-ms-source-range", sourceRange) - if options != nil && options.SourceContentMd5 != nil { - req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*options.SourceContentMd5)) + if pageBlobUploadPagesFromUrlOptions != nil && pageBlobUploadPagesFromUrlOptions.SourceContentMd5 != nil { + req.Header.Set("x-ms-source-content-md5", base64.StdEncoding.EncodeToString(*pageBlobUploadPagesFromUrlOptions.SourceContentMd5)) } - if options != nil && options.SourceContentcrc64 != nil { - req.Header.Set("x-ms-source-content-crc64", base64.StdEncoding.EncodeToString(*options.SourceContentcrc64)) + if pageBlobUploadPagesFromUrlOptions != nil && pageBlobUploadPagesFromUrlOptions.SourceContentcrc64 != nil { + req.Header.Set("x-ms-source-content-crc64", base64.StdEncoding.EncodeToString(*pageBlobUploadPagesFromUrlOptions.SourceContentcrc64)) } req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) req.Header.Set("x-ms-range", rangeParameter) - if options != nil && options.EncryptionKey != nil { - req.Header.Set("x-ms-encryption-key", *options.EncryptionKey) + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Header.Set("x-ms-encryption-key", *cpkInfo.EncryptionKey) } - if options != nil && options.EncryptionKeySha256 != nil { - req.Header.Set("x-ms-encryption-key-sha256", *options.EncryptionKeySha256) + if cpkInfo != nil && cpkInfo.EncryptionKeySha256 != nil { + req.Header.Set("x-ms-encryption-key-sha256", *cpkInfo.EncryptionKeySha256) } - if options != nil && options.EncryptionScope != nil { - req.Header.Set("x-ms-encryption-scope", *options.EncryptionScope) + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Header.Set("x-ms-encryption-scope", *cpkScopeInfo.EncryptionScope) } - if options != nil && options.LeaseId != nil { - req.Header.Set("x-ms-lease-id", *options.LeaseId) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseId != nil { + req.Header.Set("x-ms-lease-id", *leaseAccessConditions.LeaseId) } - if options != nil && options.IfSequenceNumberLessThanOrEqualTo != nil { - req.Header.Set("x-ms-if-sequence-number-le", strconv.FormatInt(*options.IfSequenceNumberLessThanOrEqualTo, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo != nil { + req.Header.Set("x-ms-if-sequence-number-le", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo, 10)) } - if options != nil && options.IfSequenceNumberLessThan != nil { - req.Header.Set("x-ms-if-sequence-number-lt", strconv.FormatInt(*options.IfSequenceNumberLessThan, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThan != nil { + req.Header.Set("x-ms-if-sequence-number-lt", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThan, 10)) } - if options != nil && options.IfSequenceNumberEqualTo != nil { - req.Header.Set("x-ms-if-sequence-number-eq", strconv.FormatInt(*options.IfSequenceNumberEqualTo, 10)) + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberEqualTo != nil { + req.Header.Set("x-ms-if-sequence-number-eq", strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)) } - if options != nil && options.IfModifiedSince != nil { - req.Header.Set("If-Modified-Since", options.IfModifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Header.Set("If-Modified-Since", modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfUnmodifiedSince != nil { - req.Header.Set("If-Unmodified-Since", options.IfUnmodifiedSince.Format(time.RFC1123)) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Header.Set("If-Unmodified-Since", modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.IfMatch != nil { - req.Header.Set("If-Match", *options.IfMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Header.Set("If-Match", *modifiedAccessConditions.IfMatch) } - if options != nil && options.IfNoneMatch != nil { - req.Header.Set("If-None-Match", *options.IfNoneMatch) + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Header.Set("If-None-Match", *modifiedAccessConditions.IfNoneMatch) } - if options != nil && options.SourceIfModifiedSince != nil { - req.Header.Set("x-ms-source-if-modified-since", options.SourceIfModifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Header.Set("x-ms-source-if-modified-since", sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfUnmodifiedSince != nil { - req.Header.Set("x-ms-source-if-unmodified-since", options.SourceIfUnmodifiedSince.Format(time.RFC1123)) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Header.Set("x-ms-source-if-unmodified-since", sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)) } - if options != nil && options.SourceIfMatch != nil { - req.Header.Set("x-ms-source-if-match", *options.SourceIfMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Header.Set("x-ms-source-if-match", *sourceModifiedAccessConditions.SourceIfMatch) } - if options != nil && options.SourceIfNoneMatch != nil { - req.Header.Set("x-ms-source-if-none-match", *options.SourceIfNoneMatch) + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Header.Set("x-ms-source-if-none-match", *sourceModifiedAccessConditions.SourceIfNoneMatch) } req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if pageBlobUploadPagesFromUrlOptions != nil && pageBlobUploadPagesFromUrlOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *pageBlobUploadPagesFromUrlOptions.RequestId) } return req, nil } @@ -1036,7 +1119,7 @@ func (client *pageBlobOperations) uploadPagesFromUrlCreateRequest(sourceUrl url. // uploadPagesFromUrlHandleResponse handles the UploadPagesFromURL response. func (client *pageBlobOperations) uploadPagesFromUrlHandleResponse(resp *azcore.Response) (*PageBlobUploadPagesFromURLResponse, error) { if !resp.HasStatusCode(http.StatusCreated) { - return nil, newStorageError(resp) + return nil, client.uploadPagesFromUrlHandleError(resp) } result := PageBlobUploadPagesFromURLResponse{RawResponse: resp.Response} if val := resp.Header.Get("ETag"); val != "" { @@ -1098,3 +1181,12 @@ func (client *pageBlobOperations) uploadPagesFromUrlHandleResponse(resp *azcore. } return &result, nil } + +// uploadPagesFromUrlHandleError handles the UploadPagesFromURL error response. +func (client *pageBlobOperations) uploadPagesFromUrlHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} diff --git a/sdk/storage/blob/2019-07-07/azblob/pagers.go b/sdk/storage/blob/2019-07-07/azblob/pagers.go index 1270e18deb79..3cb8a076dd61 100644 --- a/sdk/storage/blob/2019-07-07/azblob/pagers.go +++ b/sdk/storage/blob/2019-07-07/azblob/pagers.go @@ -28,8 +28,8 @@ type listBlobsFlatSegmentResponseHandleResponse func(*azcore.Response) (*ListBlo type listBlobsFlatSegmentResponseAdvancePage func(*ListBlobsFlatSegmentResponseResponse) (*azcore.Request, error) type listBlobsFlatSegmentResponsePager struct { - // the client for making the request - client *containerOperations + // the pipeline for making the request + pipeline azcore.Pipeline // contains the pending request request *azcore.Request // callback for handling the HTTP response @@ -58,7 +58,7 @@ func (p *listBlobsFlatSegmentResponsePager) NextPage(ctx context.Context) bool { } p.request = req } - resp, err := p.client.p.Do(ctx, p.request) + resp, err := p.pipeline.Do(ctx, p.request) if err != nil { p.err = err return false @@ -94,8 +94,8 @@ type listBlobsHierarchySegmentResponseHandleResponse func(*azcore.Response) (*Li type listBlobsHierarchySegmentResponseAdvancePage func(*ListBlobsHierarchySegmentResponseResponse) (*azcore.Request, error) type listBlobsHierarchySegmentResponsePager struct { - // the client for making the request - client *containerOperations + // the pipeline for making the request + pipeline azcore.Pipeline // contains the pending request request *azcore.Request // callback for handling the HTTP response @@ -124,7 +124,7 @@ func (p *listBlobsHierarchySegmentResponsePager) NextPage(ctx context.Context) b } p.request = req } - resp, err := p.client.p.Do(ctx, p.request) + resp, err := p.pipeline.Do(ctx, p.request) if err != nil { p.err = err return false @@ -160,8 +160,8 @@ type listContainersSegmentResponseHandleResponse func(*azcore.Response) (*ListCo type listContainersSegmentResponseAdvancePage func(*ListContainersSegmentResponseResponse) (*azcore.Request, error) type listContainersSegmentResponsePager struct { - // the client for making the request - client *serviceOperations + // the pipeline for making the request + pipeline azcore.Pipeline // contains the pending request request *azcore.Request // callback for handling the HTTP response @@ -190,7 +190,7 @@ func (p *listContainersSegmentResponsePager) NextPage(ctx context.Context) bool } p.request = req } - resp, err := p.client.p.Do(ctx, p.request) + resp, err := p.pipeline.Do(ctx, p.request) if err != nil { p.err = err return false diff --git a/sdk/storage/blob/2019-07-07/azblob/service.go b/sdk/storage/blob/2019-07-07/azblob/service.go index 5c6105238085..669eb9f4c23e 100644 --- a/sdk/storage/blob/2019-07-07/azblob/service.go +++ b/sdk/storage/blob/2019-07-07/azblob/service.go @@ -20,22 +20,22 @@ type ServiceOperations interface { // GetAccountInfo - Returns the sku name and account kind GetAccountInfo(ctx context.Context) (*ServiceGetAccountInfoResponse, error) // GetProperties - gets the properties of a storage account's Blob service, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. - GetProperties(ctx context.Context, options *ServiceGetPropertiesOptions) (*StorageServicePropertiesResponse, error) + GetProperties(ctx context.Context, serviceGetPropertiesOptions *ServiceGetPropertiesOptions) (*StorageServicePropertiesResponse, error) // 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. - GetStatistics(ctx context.Context, options *ServiceGetStatisticsOptions) (*StorageServiceStatsResponse, error) + GetStatistics(ctx context.Context, serviceGetStatisticsOptions *ServiceGetStatisticsOptions) (*StorageServiceStatsResponse, error) // GetUserDelegationKey - Retrieves a user delegation key for the Blob service. This is only a valid operation when using bearer token authentication. - GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, options *ServiceGetUserDelegationKeyOptions) (*UserDelegationKeyResponse, error) + GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, serviceGetUserDelegationKeyOptions *ServiceGetUserDelegationKeyOptions) (*UserDelegationKeyResponse, error) // ListContainersSegment - The List Containers Segment operation returns a list of the containers under the specified account - ListContainersSegment(options *ServiceListContainersSegmentOptions) (ListContainersSegmentResponsePager, error) + ListContainersSegment(serviceListContainersSegmentOptions *ServiceListContainersSegmentOptions) (ListContainersSegmentResponsePager, error) // SetProperties - Sets properties for a storage account's Blob service endpoint, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules - SetProperties(ctx context.Context, storageServiceProperties StorageServiceProperties, options *ServiceSetPropertiesOptions) (*ServiceSetPropertiesResponse, error) + SetProperties(ctx context.Context, storageServiceProperties StorageServiceProperties, serviceSetPropertiesOptions *ServiceSetPropertiesOptions) (*ServiceSetPropertiesResponse, error) // SubmitBatch - The Batch operation allows multiple API calls to be embedded into a single HTTP request. - SubmitBatch(ctx context.Context, contentLength int64, multipartContentType string, body azcore.ReadSeekCloser, options *ServiceSubmitBatchOptions) (*ServiceSubmitBatchResponse, error) + SubmitBatch(ctx context.Context, contentLength int64, multipartContentType string, body azcore.ReadSeekCloser, serviceSubmitBatchOptions *ServiceSubmitBatchOptions) (*ServiceSubmitBatchResponse, error) } // serviceOperations implements the ServiceOperations interface. type serviceOperations struct { - *Client + *client } // GetAccountInfo - Returns the sku name and account kind @@ -57,7 +57,8 @@ func (client *serviceOperations) GetAccountInfo(ctx context.Context) (*ServiceGe // getAccountInfoCreateRequest creates the GetAccountInfo request. func (client *serviceOperations) getAccountInfoCreateRequest() (*azcore.Request, error) { - u := client.u + copy := *client.u + u := © query := u.Query() query.Set("restype", "account") query.Set("comp", "properties") @@ -70,7 +71,7 @@ func (client *serviceOperations) getAccountInfoCreateRequest() (*azcore.Request, // getAccountInfoHandleResponse handles the GetAccountInfo response. func (client *serviceOperations) getAccountInfoHandleResponse(resp *azcore.Response) (*ServiceGetAccountInfoResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getAccountInfoHandleError(resp) } result := ServiceGetAccountInfoResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -98,9 +99,18 @@ func (client *serviceOperations) getAccountInfoHandleResponse(resp *azcore.Respo return &result, nil } +// getAccountInfoHandleError handles the GetAccountInfo error response. +func (client *serviceOperations) getAccountInfoHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetProperties - gets the properties of a storage account's Blob service, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. -func (client *serviceOperations) GetProperties(ctx context.Context, options *ServiceGetPropertiesOptions) (*StorageServicePropertiesResponse, error) { - req, err := client.getPropertiesCreateRequest(options) +func (client *serviceOperations) GetProperties(ctx context.Context, serviceGetPropertiesOptions *ServiceGetPropertiesOptions) (*StorageServicePropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(serviceGetPropertiesOptions) if err != nil { return nil, err } @@ -116,19 +126,20 @@ func (client *serviceOperations) GetProperties(ctx context.Context, options *Ser } // getPropertiesCreateRequest creates the GetProperties request. -func (client *serviceOperations) getPropertiesCreateRequest(options *ServiceGetPropertiesOptions) (*azcore.Request, error) { - u := client.u +func (client *serviceOperations) getPropertiesCreateRequest(serviceGetPropertiesOptions *ServiceGetPropertiesOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "service") query.Set("comp", "properties") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if serviceGetPropertiesOptions != nil && serviceGetPropertiesOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*serviceGetPropertiesOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if serviceGetPropertiesOptions != nil && serviceGetPropertiesOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *serviceGetPropertiesOptions.RequestId) } return req, nil } @@ -136,7 +147,7 @@ func (client *serviceOperations) getPropertiesCreateRequest(options *ServiceGetP // getPropertiesHandleResponse handles the GetProperties response. func (client *serviceOperations) getPropertiesHandleResponse(resp *azcore.Response) (*StorageServicePropertiesResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getPropertiesHandleError(resp) } result := StorageServicePropertiesResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -151,9 +162,18 @@ func (client *serviceOperations) getPropertiesHandleResponse(resp *azcore.Respon return &result, resp.UnmarshalAsXML(&result.StorageServiceProperties) } +// getPropertiesHandleError handles the GetProperties error response. +func (client *serviceOperations) getPropertiesHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // 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. -func (client *serviceOperations) GetStatistics(ctx context.Context, options *ServiceGetStatisticsOptions) (*StorageServiceStatsResponse, error) { - req, err := client.getStatisticsCreateRequest(options) +func (client *serviceOperations) GetStatistics(ctx context.Context, serviceGetStatisticsOptions *ServiceGetStatisticsOptions) (*StorageServiceStatsResponse, error) { + req, err := client.getStatisticsCreateRequest(serviceGetStatisticsOptions) if err != nil { return nil, err } @@ -169,19 +189,20 @@ func (client *serviceOperations) GetStatistics(ctx context.Context, options *Ser } // getStatisticsCreateRequest creates the GetStatistics request. -func (client *serviceOperations) getStatisticsCreateRequest(options *ServiceGetStatisticsOptions) (*azcore.Request, error) { - u := client.u +func (client *serviceOperations) getStatisticsCreateRequest(serviceGetStatisticsOptions *ServiceGetStatisticsOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "service") query.Set("comp", "stats") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if serviceGetStatisticsOptions != nil && serviceGetStatisticsOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*serviceGetStatisticsOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if serviceGetStatisticsOptions != nil && serviceGetStatisticsOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *serviceGetStatisticsOptions.RequestId) } return req, nil } @@ -189,7 +210,7 @@ func (client *serviceOperations) getStatisticsCreateRequest(options *ServiceGetS // getStatisticsHandleResponse handles the GetStatistics response. func (client *serviceOperations) getStatisticsHandleResponse(resp *azcore.Response) (*StorageServiceStatsResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getStatisticsHandleError(resp) } result := StorageServiceStatsResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -211,9 +232,18 @@ func (client *serviceOperations) getStatisticsHandleResponse(resp *azcore.Respon return &result, resp.UnmarshalAsXML(&result.StorageServiceStats) } +// getStatisticsHandleError handles the GetStatistics error response. +func (client *serviceOperations) getStatisticsHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // GetUserDelegationKey - Retrieves a user delegation key for the Blob service. This is only a valid operation when using bearer token authentication. -func (client *serviceOperations) GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, options *ServiceGetUserDelegationKeyOptions) (*UserDelegationKeyResponse, error) { - req, err := client.getUserDelegationKeyCreateRequest(keyInfo, options) +func (client *serviceOperations) GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, serviceGetUserDelegationKeyOptions *ServiceGetUserDelegationKeyOptions) (*UserDelegationKeyResponse, error) { + req, err := client.getUserDelegationKeyCreateRequest(keyInfo, serviceGetUserDelegationKeyOptions) if err != nil { return nil, err } @@ -229,19 +259,20 @@ func (client *serviceOperations) GetUserDelegationKey(ctx context.Context, keyIn } // getUserDelegationKeyCreateRequest creates the GetUserDelegationKey request. -func (client *serviceOperations) getUserDelegationKeyCreateRequest(keyInfo KeyInfo, options *ServiceGetUserDelegationKeyOptions) (*azcore.Request, error) { - u := client.u +func (client *serviceOperations) getUserDelegationKeyCreateRequest(keyInfo KeyInfo, serviceGetUserDelegationKeyOptions *ServiceGetUserDelegationKeyOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "service") query.Set("comp", "userdelegationkey") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if serviceGetUserDelegationKeyOptions != nil && serviceGetUserDelegationKeyOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*serviceGetUserDelegationKeyOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPost, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if serviceGetUserDelegationKeyOptions != nil && serviceGetUserDelegationKeyOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *serviceGetUserDelegationKeyOptions.RequestId) } return req, req.MarshalAsXML(keyInfo) } @@ -249,7 +280,7 @@ func (client *serviceOperations) getUserDelegationKeyCreateRequest(keyInfo KeyIn // getUserDelegationKeyHandleResponse handles the GetUserDelegationKey response. func (client *serviceOperations) getUserDelegationKeyHandleResponse(resp *azcore.Response) (*UserDelegationKeyResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.getUserDelegationKeyHandleError(resp) } result := UserDelegationKeyResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -271,14 +302,23 @@ func (client *serviceOperations) getUserDelegationKeyHandleResponse(resp *azcore return &result, resp.UnmarshalAsXML(&result.UserDelegationKey) } +// getUserDelegationKeyHandleError handles the GetUserDelegationKey error response. +func (client *serviceOperations) getUserDelegationKeyHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // ListContainersSegment - The List Containers Segment operation returns a list of the containers under the specified account -func (client *serviceOperations) ListContainersSegment(options *ServiceListContainersSegmentOptions) (ListContainersSegmentResponsePager, error) { - req, err := client.listContainersSegmentCreateRequest(options) +func (client *serviceOperations) ListContainersSegment(serviceListContainersSegmentOptions *ServiceListContainersSegmentOptions) (ListContainersSegmentResponsePager, error) { + req, err := client.listContainersSegmentCreateRequest(serviceListContainersSegmentOptions) if err != nil { return nil, err } return &listContainersSegmentResponsePager{ - client: client, + pipeline: client.p, request: req, responder: client.listContainersSegmentHandleResponse, advancer: func(resp *ListContainersSegmentResponseResponse) (*azcore.Request, error) { @@ -295,27 +335,28 @@ func (client *serviceOperations) ListContainersSegment(options *ServiceListConta } // listContainersSegmentCreateRequest creates the ListContainersSegment request. -func (client *serviceOperations) listContainersSegmentCreateRequest(options *ServiceListContainersSegmentOptions) (*azcore.Request, error) { - u := client.u +func (client *serviceOperations) listContainersSegmentCreateRequest(serviceListContainersSegmentOptions *ServiceListContainersSegmentOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "list") - if options != nil && options.Prefix != nil { - query.Set("prefix", *options.Prefix) + if serviceListContainersSegmentOptions != nil && serviceListContainersSegmentOptions.Prefix != nil { + query.Set("prefix", *serviceListContainersSegmentOptions.Prefix) } - if options != nil && options.Marker != nil { - query.Set("marker", *options.Marker) + if serviceListContainersSegmentOptions != nil && serviceListContainersSegmentOptions.Marker != nil { + query.Set("marker", *serviceListContainersSegmentOptions.Marker) } - if options != nil && options.Maxresults != nil { - query.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + if serviceListContainersSegmentOptions != nil && serviceListContainersSegmentOptions.Maxresults != nil { + query.Set("maxresults", strconv.FormatInt(int64(*serviceListContainersSegmentOptions.Maxresults), 10)) } - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if serviceListContainersSegmentOptions != nil && serviceListContainersSegmentOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*serviceListContainersSegmentOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodGet, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if serviceListContainersSegmentOptions != nil && serviceListContainersSegmentOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *serviceListContainersSegmentOptions.RequestId) } return req, nil } @@ -323,7 +364,7 @@ func (client *serviceOperations) listContainersSegmentCreateRequest(options *Ser // listContainersSegmentHandleResponse handles the ListContainersSegment response. func (client *serviceOperations) listContainersSegmentHandleResponse(resp *azcore.Response) (*ListContainersSegmentResponseResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.listContainersSegmentHandleError(resp) } result := ListContainersSegmentResponseResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -338,9 +379,18 @@ func (client *serviceOperations) listContainersSegmentHandleResponse(resp *azcor return &result, resp.UnmarshalAsXML(&result.EnumerationResults) } +// listContainersSegmentHandleError handles the ListContainersSegment error response. +func (client *serviceOperations) listContainersSegmentHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SetProperties - Sets properties for a storage account's Blob service endpoint, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules -func (client *serviceOperations) SetProperties(ctx context.Context, storageServiceProperties StorageServiceProperties, options *ServiceSetPropertiesOptions) (*ServiceSetPropertiesResponse, error) { - req, err := client.setPropertiesCreateRequest(storageServiceProperties, options) +func (client *serviceOperations) SetProperties(ctx context.Context, storageServiceProperties StorageServiceProperties, serviceSetPropertiesOptions *ServiceSetPropertiesOptions) (*ServiceSetPropertiesResponse, error) { + req, err := client.setPropertiesCreateRequest(storageServiceProperties, serviceSetPropertiesOptions) if err != nil { return nil, err } @@ -356,19 +406,20 @@ func (client *serviceOperations) SetProperties(ctx context.Context, storageServi } // setPropertiesCreateRequest creates the SetProperties request. -func (client *serviceOperations) setPropertiesCreateRequest(storageServiceProperties StorageServiceProperties, options *ServiceSetPropertiesOptions) (*azcore.Request, error) { - u := client.u +func (client *serviceOperations) setPropertiesCreateRequest(storageServiceProperties StorageServiceProperties, serviceSetPropertiesOptions *ServiceSetPropertiesOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("restype", "service") query.Set("comp", "properties") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if serviceSetPropertiesOptions != nil && serviceSetPropertiesOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*serviceSetPropertiesOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPut, *u) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if serviceSetPropertiesOptions != nil && serviceSetPropertiesOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *serviceSetPropertiesOptions.RequestId) } return req, req.MarshalAsXML(storageServiceProperties) } @@ -376,7 +427,7 @@ func (client *serviceOperations) setPropertiesCreateRequest(storageServiceProper // setPropertiesHandleResponse handles the SetProperties response. func (client *serviceOperations) setPropertiesHandleResponse(resp *azcore.Response) (*ServiceSetPropertiesResponse, error) { if !resp.HasStatusCode(http.StatusAccepted) { - return nil, newStorageError(resp) + return nil, client.setPropertiesHandleError(resp) } result := ServiceSetPropertiesResponse{RawResponse: resp.Response} if val := resp.Header.Get("x-ms-client-request-id"); val != "" { @@ -391,9 +442,18 @@ func (client *serviceOperations) setPropertiesHandleResponse(resp *azcore.Respon return &result, nil } +// setPropertiesHandleError handles the SetProperties error response. +func (client *serviceOperations) setPropertiesHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +} + // SubmitBatch - The Batch operation allows multiple API calls to be embedded into a single HTTP request. -func (client *serviceOperations) SubmitBatch(ctx context.Context, contentLength int64, multipartContentType string, body azcore.ReadSeekCloser, options *ServiceSubmitBatchOptions) (*ServiceSubmitBatchResponse, error) { - req, err := client.submitBatchCreateRequest(contentLength, multipartContentType, body, options) +func (client *serviceOperations) SubmitBatch(ctx context.Context, contentLength int64, multipartContentType string, body azcore.ReadSeekCloser, serviceSubmitBatchOptions *ServiceSubmitBatchOptions) (*ServiceSubmitBatchResponse, error) { + req, err := client.submitBatchCreateRequest(contentLength, multipartContentType, body, serviceSubmitBatchOptions) if err != nil { return nil, err } @@ -409,12 +469,13 @@ func (client *serviceOperations) SubmitBatch(ctx context.Context, contentLength } // submitBatchCreateRequest creates the SubmitBatch request. -func (client *serviceOperations) submitBatchCreateRequest(contentLength int64, multipartContentType string, body azcore.ReadSeekCloser, options *ServiceSubmitBatchOptions) (*azcore.Request, error) { - u := client.u +func (client *serviceOperations) submitBatchCreateRequest(contentLength int64, multipartContentType string, body azcore.ReadSeekCloser, serviceSubmitBatchOptions *ServiceSubmitBatchOptions) (*azcore.Request, error) { + copy := *client.u + u := © query := u.Query() query.Set("comp", "batch") - if options != nil && options.Timeout != nil { - query.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + if serviceSubmitBatchOptions != nil && serviceSubmitBatchOptions.Timeout != nil { + query.Set("timeout", strconv.FormatInt(int64(*serviceSubmitBatchOptions.Timeout), 10)) } u.RawQuery = query.Encode() req := azcore.NewRequest(http.MethodPost, *u) @@ -422,8 +483,8 @@ func (client *serviceOperations) submitBatchCreateRequest(contentLength int64, m req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) req.Header.Set("Content-Type", multipartContentType) req.Header.Set("x-ms-version", "2019-07-07") - if options != nil && options.RequestId != nil { - req.Header.Set("x-ms-client-request-id", *options.RequestId) + if serviceSubmitBatchOptions != nil && serviceSubmitBatchOptions.RequestId != nil { + req.Header.Set("x-ms-client-request-id", *serviceSubmitBatchOptions.RequestId) } return req, req.MarshalAsXML(body) } @@ -431,7 +492,7 @@ func (client *serviceOperations) submitBatchCreateRequest(contentLength int64, m // submitBatchHandleResponse handles the SubmitBatch response. func (client *serviceOperations) submitBatchHandleResponse(resp *azcore.Response) (*ServiceSubmitBatchResponse, error) { if !resp.HasStatusCode(http.StatusOK) { - return nil, newStorageError(resp) + return nil, client.submitBatchHandleError(resp) } result := ServiceSubmitBatchResponse{RawResponse: resp.Response} if val := resp.Header.Get("Content-Type"); val != "" { @@ -445,3 +506,12 @@ func (client *serviceOperations) submitBatchHandleResponse(resp *azcore.Response } return &result, nil } + +// submitBatchHandleError handles the SubmitBatch error response. +func (client *serviceOperations) submitBatchHandleError(resp *azcore.Response) error { + var err StorageError + if err := resp.UnmarshalAsXML(&err); err != nil { + return err + } + return err +}