pax_global_header 0000666 0000000 0000000 00000000064 14232154237 0014515 g ustar 00root root 0000000 0000000 52 comment=19cebee2d658f7ef0475eeb4abd208a11225774f
giovanni-0.20.0/ 0000775 0000000 0000000 00000000000 14232154237 0013406 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/.github/ 0000775 0000000 0000000 00000000000 14232154237 0014746 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14232154237 0017003 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/.github/workflows/go_test.yml 0000664 0000000 0000000 00000000770 14232154237 0021176 0 ustar 00root root 0000000 0000000 name: Go Test
on:
push:
branches:
- master
pull_request:
paths:
- .github/**
- go.mod
- go.sum
- storage/**
- testhelpers/**
- version/**
env:
GO_VERSION: "1.14.4"
jobs:
go_test:
name: go test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: ${{ env.GO_VERSION }}
- run: |
go mod download
go test -v ./... -timeout=300s
giovanni-0.20.0/.gitignore 0000664 0000000 0000000 00000000051 14232154237 0015372 0 ustar 00root root 0000000 0000000 vendor/
.idea/
example/example
.DS_Store
giovanni-0.20.0/LICENSE 0000664 0000000 0000000 00000025354 14232154237 0014424 0 ustar 00root root 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
giovanni-0.20.0/README.md 0000664 0000000 0000000 00000011501 14232154237 0014663 0 ustar 00root root 0000000 0000000 # Giovanni
An alternative Azure Storage SDK for Go
---
This repository is an alternative Azure Storage SDK for Go; which supports for:
- The [Blob Storage APIs](https://docs.microsoft.com/en-us/rest/api/storageservices/blob-service-rest-api)
- The [DataLakeStorage Gen2 APIs](https://docs.microsoft.com/en-us/rest/api/storageservices/data-lake-storage-gen2)
- The [File Storage APIs](https://docs.microsoft.com/en-us/rest/api/storageservices/file-service-rest-api)
- The [Queue Storage APIs](https://docs.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api)
- The [Table Storage APIs](https://docs.microsoft.com/en-us/rest/api/storageservices/table-service-rest-api)
At this time we support the following API Versions:
* `2020-08-04` (`./storage/2020-08-04`)
* `2019-12-12` (`./storage/2019-12-12`)
* `2018-11-09` (`./storage/2018-11-09`)
* `2018-03-28` (`./storage/2018-03-28`)
* `2017-07-29` (`./storage/2017-07-29`)
We're also open to supporting other versions of the Azure Storage SDK as necessary.
Documentation for how to use each SDK can be found within the README for that SDK version - for example [here's the README for 2020-08-04](storage/2020-08-04/README.md).
Each Package also contains Unit and Acceptance tests to ensure that the functionality works; instructions on how to run the tests can be found below.
## Mission Statement
Fundamentally: developers should be able to pick which version of the Azure API they target using this SDK.
As such, there's two main goals here:
* New API Versions will be added additively to the `storage` folder.
* Any supported API Versions will continue to exist in the `storage` folder until they're EOL'd/stop working.
To ensure that each of these scenarios is possible - we have Acceptance and Unit Tests to confirm that the functionality in these versions works - and will use SemVer as appropriate.
## Future Enhancements
At this time this SDK is mostly feature complete, with a couple of notable additions (since we didn't need them).
Whilst it's possible to create Snapshots (for example, of a Container) - at this time most SDK calls don't support specifying the optional query-string value for `snapshot`.
In addition, we also don't support the `timeout` querystring on every API call; this is because instead all SDK methods take a `context` object, which allows a timeout to be set (albeit on the Client rather than the Remote API Call).
In both instances this is because we didn't need this functionality for our use-cases - but feel free to send a PR if you need this.
## Licence
Apache 2.0
## Technical Implementation
This SDK makes use of the standard Preparer-Sender-Responder pattern found in [Azure/go-autorest](https://github.com/Azure/go-autorest) - which means that this SDK should be familiar and compatible with [the Azure SDK for Go](https://github.com/Azure/azure-sdk-for-go).
Depending on the API Version / API being used - different authentication mechanisms are possible (see the README within the specific SDK for more info ([example](XXX)). In all cases one of the following Authorizers will be required:
* An Authorizer for Azure Active Directory
* A SharedKeyLite Authorizer (for Blob, Queue and Table Storage)
* A SharedKeyLite Authorizer (for Table Storage)
Examples for all of these can be found below in [the Examples Directory](examples/).
There's a [Pull Request open adding both a SharedKey and a SharedKeyLite authorizer to Azure/go-autorest](http://github.com/Azure/go-autorest/pull/416)
## Running the Tests
Each package contains both Unit and Acceptance Tests which provision a real Storage Account on Azure, and then run tests against that.
To run those, the following Environment Variables need to be set:
* `ARM_TENANT_ID` - The ID of the Tenant where tests should be run, such as `00000000-0000-0000-0000-000000000000`.
* `ARM_SUBSCRIPTION_ID` - The ID of the Subscription where tests should be run, such as `00000000-0000-0000-0000-000000000000`.
* `ARM_CLIENT_ID` - The ID of the AzureAD Application (also known as a Client ID), such as `00000000-0000-0000-0000-000000000000`.
* `ARM_CLIENT_SECRET` - The Client Secret/Password for a Service Principal where tests should be run.
* `ARM_ENVIRONMENT` - The name of the Azure Environment where the tests should be run, such as `Public` or `Germany`.
* `ARM_TEST_LOCATION` - The name of the Azure Region where resources provisioned by the tests should be created, such as `West Europe`.
* `ACCTEST` - confirms that you want the tests to be run, set this to any value.
Once those Environment Variables are set - you should be able to run:
```bash
$ ACCTEST=1 go test -v ./storage/...
```
You can also run them for a specific API version by running:
```bash
$ ACCTEST=1 go test -v ./storage/2020-08-04/...
```
## Debugging
You can see the Requests/Responses from this SDK by setting the Environment Variable `TEST_LOG` to any value.
giovanni-0.20.0/example/ 0000775 0000000 0000000 00000000000 14232154237 0015041 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/example/azuread-auth/ 0000775 0000000 0000000 00000000000 14232154237 0017433 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/example/azuread-auth/README.md 0000664 0000000 0000000 00000001416 14232154237 0020714 0 ustar 00root root 0000000 0000000 ## Example: using Azure Active Directory authentication
This example provisions a Storage Container using Azure Active Directory for authentication.
To run this example you need the following Environment Variables set:
* `ARM_CLIENT_ID` - The UUID of the Service Principal/Application
* `ARM_CLIENT_SECRET` - The Secret associated with the Service Principal
* `ARM_ENVIRONMENT` - The Azure Environment (`public`, `germany` etc)
* `ARM_SUBSCRIPTION_ID` - The UUID of the Azure Subscription
* `ARM_TENANT_ID` - The UUID of the Azure Tenant
You also need to update `main.go` to set the variable `storageAccountName` to an existing Storage Account (since we don't provision one for you).
Assuming you've got Go installed - you can then run this using:
```bash
$ go run main.go
``` giovanni-0.20.0/example/azuread-auth/main.go 0000664 0000000 0000000 00000005362 14232154237 0020714 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"github.com/Azure/go-autorest/autorest"
"github.com/hashicorp/go-azure-helpers/authentication"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
)
func main() {
log.Printf("[DEBUG] Started..")
// NOTE: fill this in
storageAccountName := "example"
log.Printf("[DEBUG] Building Client..")
client, err := buildClient()
if err != nil {
panic(fmt.Errorf("Error building client: %s", err))
}
ctx := context.TODO()
containerName := "armauth"
input := containers.CreateInput{
AccessLevel: containers.Private,
MetaData: map[string]string{
"hello": "world",
},
}
log.Printf("[DEBUG] Creating Container..")
if _, err := client.ContainersClient.Create(ctx, storageAccountName, containerName, input); err != nil {
panic(fmt.Errorf("Error creating container: %s", err))
}
log.Printf("[DEBUG] Retrieving Container..")
container, err := client.ContainersClient.GetProperties(ctx, storageAccountName, containerName)
if err != nil {
panic(fmt.Errorf("Error reading properties for container: %s", err))
}
log.Printf("[DEBUG] MetaData: %+v", container.MetaData)
}
type Client struct {
ContainersClient containers.Client
}
func buildClient() (*Client, error) {
// we're using github.com/hashicorp/go-azure-helpers since it makes this simpler
// but you can use an Authorizer from github.com/Azure/go-autorest directly too
builder := &authentication.Builder{
SubscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"),
ClientID: os.Getenv("ARM_CLIENT_ID"),
ClientSecret: os.Getenv("ARM_CLIENT_SECRET"),
TenantID: os.Getenv("ARM_TENANT_ID"),
Environment: os.Getenv("ARM_ENVIRONMENT"),
// Feature Toggles
SupportsClientSecretAuth: true,
SupportsAzureCliToken: true,
}
config, err := builder.Build()
if err != nil {
return nil, fmt.Errorf("Error building AzureRM Client: %s", err)
}
env, err := authentication.DetermineEnvironment(config.Environment)
if err != nil {
return nil, err
}
oauthConfig, err := config.BuildOAuthConfig(env.ActiveDirectoryEndpoint)
if err != nil {
return nil, err
}
// OAuthConfigForTenant returns a pointer, which can be nil.
if oauthConfig == nil {
return nil, fmt.Errorf("Unable to configure OAuthConfig for tenant %s", config.TenantID)
}
// support for HTTP Proxies
sender := autorest.DecorateSender(&http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
},
})
storageAuth, err := config.GetAuthorizationToken(sender, oauthConfig, "https://storage.azure.com/")
if err != nil {
return nil, err
}
containersClient := containers.New()
containersClient.Client.Authorizer = storageAuth
result := &Client{
ContainersClient: containersClient,
}
return result, nil
}
giovanni-0.20.0/example/file-auth/ 0000775 0000000 0000000 00000000000 14232154237 0016717 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/example/file-auth/README.md 0000664 0000000 0000000 00000001012 14232154237 0020170 0 ustar 00root root 0000000 0000000 ## Example: using a Shared Key
This example provisions a Storage Container using a Shared Key for authentication.
To run this example you need the following Environment Variables set:
* `ARM_ENVIRONMENT` - The Azure Environment (`public`, `germany` etc)
You also need to update `main.go` to set the variable `storageAccountName` and `storageAccountKey` to an existing Storage Account (since we don't provision one for you).
Assuming you've got Go installed - you can then run this using:
```bash
$ go run main.go
``` giovanni-0.20.0/example/file-auth/main.go 0000664 0000000 0000000 00000003425 14232154237 0020176 0 ustar 00root root 0000000 0000000 package main
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/go-autorest/autorest"
"github.com/hashicorp/go-azure-helpers/authentication"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
)
func main() {
log.Printf("[DEBUG] Started..")
// NOTE: fill this in
storageAccountName := "example"
storageAccountKey := "example"
log.Printf("[DEBUG] Building Client..")
client, err := buildClient(storageAccountName, storageAccountKey)
if err != nil {
panic(fmt.Errorf("Error building client: %s", err))
}
ctx := context.TODO()
containerName := "armauth"
input := containers.CreateInput{
AccessLevel: containers.Private,
MetaData: map[string]string{
"hello": "world",
},
}
log.Printf("[DEBUG] Creating Container..")
if _, err := client.ContainersClient.Create(ctx, storageAccountName, containerName, input); err != nil {
panic(fmt.Errorf("Error creating container: %s", err))
}
log.Printf("[DEBUG] Retrieving Container..")
container, err := client.ContainersClient.GetProperties(ctx, storageAccountName, containerName)
if err != nil {
panic(fmt.Errorf("Error reading properties for container: %s", err))
}
log.Printf("[DEBUG] MetaData: %+v", container.MetaData)
}
type Client struct {
ContainersClient containers.Client
}
func buildClient(accountName, accountKey string) (*Client, error) {
env, err := authentication.DetermineEnvironment(os.Getenv("ARM_ENVIRONMENT"))
if err != nil {
return nil, err
}
storageAuth, err := autorest.NewSharedKeyAuthorizer(accountName, accountKey, autorest.SharedKeyLite)
if err != nil {
return nil, err
}
containersClient := containers.NewWithEnvironment(*env)
containersClient.Client.Authorizer = storageAuth
result := &Client{
ContainersClient: containersClient,
}
return result, nil
}
giovanni-0.20.0/go.mod 0000664 0000000 0000000 00000001215 14232154237 0014513 0 ustar 00root root 0000000 0000000 module github.com/tombuildsstuff/giovanni
go 1.13
require (
github.com/Azure/azure-sdk-for-go v56.0.0+incompatible
github.com/Azure/go-autorest/autorest v0.11.19
github.com/Azure/go-autorest/autorest/adal v0.9.14 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/google/uuid v1.1.1
github.com/hashicorp/go-azure-helpers v0.12.0
github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
)
giovanni-0.20.0/go.sum 0000664 0000000 0000000 00000015564 14232154237 0014554 0 ustar 00root root 0000000 0000000 github.com/Azure/azure-sdk-for-go v45.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v56.0.0+incompatible h1:jp/df9XKIJYtf4HIVA9cgmVbQpp12lxk73pcHvDsgDE=
github.com/Azure/azure-sdk-for-go v56.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
github.com/Azure/go-autorest/autorest v0.11.19 h1:7/IqD2fEYVha1EPeaiytVKhzmPV223pfkRIQUGOK2IE=
github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.14 h1:G8hexQdV5D4khOXrWG2YuLCFKhWYmWD8bHYaXN5ophk=
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-azure-helpers v0.12.0 h1:7D0mFSyP3EfHu1ySubserIsnUWY87HMzzTWOB7ASwRU=
github.com/hashicorp/go-azure-helpers v0.12.0/go.mod h1:Zc3v4DNeX6PDdy7NljlYpnrdac1++qNW0I4U+ofGwpg=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
giovanni-0.20.0/storage/ 0000775 0000000 0000000 00000000000 14232154237 0015052 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/ 0000775 0000000 0000000 00000000000 14232154237 0016117 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/README.md 0000664 0000000 0000000 00000001003 14232154237 0017370 0 ustar 00root root 0000000 0000000 # Storage API Version 2017-07-29
The following API's are supported by this SDK - more information about each SDK can be found within the README in each package.
## Blob Storage
- [Blobs API](blob/blobs)
- [Containers API](blob/containers)
## File Storage
- [Directories API](file/directories)
- [Files API](file/files)
- [Shares API](file/shares)
## Queue Storage
- [Queues API](queue/queues)
- [Messages API](queue/messages)
## Table Storage
- [Entities API](table/entities)
- [Tables API](table/tables)
giovanni-0.20.0/storage/2017-07-29/blob/ 0000775 0000000 0000000 00000000000 14232154237 0017035 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/blob/blobs/ 0000775 0000000 0000000 00000000000 14232154237 0020136 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/blob/blobs/README.md 0000664 0000000 0000000 00000002142 14232154237 0021414 0 ustar 00root root 0000000 0000000 ## Blob Storage Blobs SDK for API version 2017-07-29
This package allows you to interact with the Blobs Blob Storage API
### Supported Authorizers
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/blobs"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
fileName := "example-large-file.iso"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
blobClient := blobs.New()
blobClient.Client.Authorizer = storageAuth
ctx := context.TODO()
copyInput := blobs.CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/blob/blobs/append_block.go 0000664 0000000 0000000 00000014462 14232154237 0023115 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AppendBlockInput struct {
// 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 an AppendPositionConditionNotMet
// error (HTTP status code 412 – Precondition Failed)
BlobConditionAppendPosition *int64
// 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
// an MaxBlobSizeConditionNotMet error (HTTP status code 412 – Precondition Failed).
BlobConditionMaxSize *int64
// The Bytes which should be appended to the end of this Append Blob.
// This can either be nil, which creates an empty blob, or a byte array
Content *[]byte
// An MD5 hash of the block content.
// This hash is used to verify the integrity of the block during transport.
// When this header is specified, the storage service compares the hash of the content
// that has arrived with this header value.
//
// Note that this MD5 hash is not stored with the blob.
// If the two hashes do not match, the operation will fail with error code 400 (Bad Request).
ContentMD5 *string
// Required if the blob has an active lease.
// To perform this operation on a blob with an active lease, specify the valid lease ID for this header.
LeaseID *string
}
type AppendBlockResult struct {
autorest.Response
BlobAppendOffset string
BlobCommittedBlockCount int64
ContentMD5 string
ETag string
LastModified string
}
// AppendBlock commits a new block of data to the end of an existing append blob.
func (client Client) AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) > (4*1024*1024) {
return result, validation.NewError("files.Client", "PutByteRange", "`input.Content` must be at most 4MB.")
}
req, err := client.AppendBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", nil, "Failure preparing request")
return
}
resp, err := client.AppendBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure sending request")
return
}
result, err = client.AppendBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure responding to request")
return
}
return
}
// AppendBlockPreparer prepares the AppendBlock request.
func (client Client) AppendBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "appendblock"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.BlobConditionAppendPosition != nil {
headers["x-ms-blob-condition-appendpos"] = *input.BlobConditionAppendPosition
}
if input.BlobConditionMaxSize != nil {
headers["x-ms-blob-condition-maxsize"] = *input.BlobConditionMaxSize
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AppendBlockSender sends the AppendBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AppendBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AppendBlockResponder handles the response to the AppendBlock request. The method always
// closes the http.Response Body.
func (client Client) AppendBlockResponder(resp *http.Response) (result AppendBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobAppendOffset = resp.Header.Get("x-ms-blob-append-offset")
result.ContentMD5 = resp.Header.Get("ETag")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
if v := resp.Header.Get("x-ms-blob-committed-block-count"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
result.BlobCommittedBlockCount = int64(i)
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/blob_append_test.go 0000664 0000000 0000000 00000011325 14232154237 0023773 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestAppendBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Append Blob..")
if _, err := blobClient.PutAppendBlob(ctx, accountName, containerName, fileName, PutAppendBlobInput{}); err != nil {
t.Fatalf("Error putting append blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 0 {
t.Fatalf("Expected Content-Length to be 0 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending First Block..")
appendInput := AppendBlockInput{
Content: &[]byte{
12,
48,
93,
76,
29,
10,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending first block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 6 {
t.Fatalf("Expected Content-Length to be 6 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending Second Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
92,
62,
64,
47,
83,
77,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Second block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 12 {
t.Fatalf("Expected Content-Length to be 12 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Acquiring Lease..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error acquiring Lease: %s", err)
}
t.Logf("[DEBUG] Lease ID is %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Appending Third Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
64,
35,
28,
93,
11,
23,
},
LeaseID: &leaseDetails.LeaseID,
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Third block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 18 {
t.Fatalf("Expected Content-Length to be 18 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Breaking Lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseDetails.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
t.Logf("[DEBUG] Deleting Lease..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/blob_page_test.go 0000664 0000000 0000000 00000005536 14232154237 0023447 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPageBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Page Blob..")
fileSize := int64(10240000)
if _, err := blobClient.PutPageBlob(ctx, accountName, containerName, fileName, PutPageBlobInput{
BlobContentLengthBytes: fileSize,
}); err != nil {
t.Fatalf("Error putting page blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != fileSize {
t.Fatalf("Expected Content-Length to be %d but it was %d", fileSize, props.ContentLength)
}
for iteration := 1; iteration <= 3; iteration++ {
t.Logf("[DEBUG] Putting Page %d of 3..", iteration)
byteArray := func() []byte {
o := make([]byte, 0)
for i := 0; i < 512; i++ {
o = append(o, byte(i))
}
return o
}()
startByte := int64(512 * iteration)
endByte := int64(startByte + 511)
putPageInput := PutPageUpdateInput{
StartByte: startByte,
EndByte: endByte,
Content: byteArray,
}
if _, err := blobClient.PutPageUpdate(ctx, accountName, containerName, fileName, putPageInput); err != nil {
t.Fatalf("Error putting page: %s", err)
}
}
t.Logf("[DEBUG] Deleting..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/client.go 0000664 0000000 0000000 00000001117 14232154237 0021743 0 ustar 00root root 0000000 0000000 package blobs
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/copy.go 0000664 0000000 0000000 00000022706 14232154237 0021446 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the name of the source blob or file.
// Beginning with version 2012-02-12, this value may be a URL of up to 2 KB in length that specifies a blob.
// The value should be URL-encoded as it would appear in a request URI.
// A source blob in the same storage account can be authenticated via Shared Key.
// However, if the source is a blob in another account,
// the source blob must either be public or must be authenticated via a shared access signature.
// If the source blob is public, no authentication is required to perform the copy operation.
//
// Beginning with version 2015-02-21, the source object may be a file in the Azure File service.
// If the source object is a file that is to be copied to a blob, then the source file must be authenticated
// using a shared access signature, whether it resides in the same account or in a different account.
//
// Only storage accounts created on or after June 7th, 2012 allow the Copy Blob operation to
// copy from another storage account.
CopySource string
// The ID of the Lease
// Required if the destination blob has an active lease.
// The lease ID specified for this header must match the lease ID of the destination blob.
// If the request does not include the lease ID or it is not valid,
// the operation fails with status code 412 (Precondition Failed).
//
// If this header is specified and the destination blob does not currently have an active lease,
// the operation will also fail with status code 412 (Precondition Failed).
LeaseID *string
// The ID of the Lease on the Source Blob
// Specify to perform the Copy Blob operation only if the lease ID matches the active lease ID of the source blob.
SourceLeaseID *string
// For page blobs on a premium account only. Specifies the tier to be set on the target blob
AccessTier *AccessTier
// 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.
MetaData map[string]string
// An ETag value.
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value matches the ETag value for an existing destination blob.
// If the ETag for the destination blob does not match the ETag specified for If-Match,
// the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value, or the wildcard character (*).
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value does not match the ETag value for the destination blob.
// Specify the wildcard character (*) to perform the operation only if the destination blob does not exist.
// If the specified condition isn't met, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has been modified since the specified date/time.
// If the destination blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has not been modified since the specified date/time.
// If the destination blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value.
// Specify this conditional header to copy the source blob only if its ETag matches the value specified.
// If the ETag values do not match, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfMatch *string
// An ETag value.
// Specify this conditional header to copy the blob only if its ETag does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has been modified
// since the specified date/time.
// If the source blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has not been modified
// since the specified date/time.
// If the source blob has been modified, the Blob service returns status code 412 (Precondition Failed).
// This header cannot be specified if the source is an Azure File.
SourceIfUnmodifiedSince *string
}
type CopyResult struct {
autorest.Response
CopyID string
CopyStatus string
}
// Copy copies a blob to a destination within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
req, err := client.CopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": autorest.Encode("header", input.CopySource),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SourceLeaseID != nil {
headers["x-ms-source-lease-id"] = *input.SourceLeaseID
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.SourceIfMatch != nil {
headers["x-ms-source-if-match"] = *input.SourceIfMatch
}
if input.SourceIfNoneMatch != nil {
headers["x-ms-source-if-none-match"] = *input.SourceIfNoneMatch
}
if input.SourceIfModifiedSince != nil {
headers["x-ms-source-if-modified-since"] = *input.SourceIfModifiedSince
}
if input.SourceIfUnmodifiedSince != nil {
headers["x-ms-source-if-unmodified-since"] = *input.SourceIfUnmodifiedSince
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/copy_abort.go 0000664 0000000 0000000 00000007451 14232154237 0022635 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AbortCopyInput struct {
// The Copy ID which should be aborted
CopyID string
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// AbortCopy aborts a pending Copy Blob operation, and leaves a destination blob with zero length and full metadata.
func (client Client) AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`blobName` cannot be an empty string.")
}
if input.CopyID == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`input.CopyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", input.CopyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/copy_and_wait.go 0000664 0000000 0000000 00000002050 14232154237 0023302 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"time"
)
// CopyAndWait copies a blob to a destination within the storage account and waits for it to finish copying.
func (client Client) CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error {
if _, err := client.Copy(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
for true {
getInput := GetPropertiesInput{
LeaseID: input.LeaseID,
}
getResult, err := client.GetProperties(ctx, accountName, containerName, blobName, getInput)
if err != nil {
return fmt.Errorf("")
}
switch getResult.CopyStatus {
case Aborted:
return fmt.Errorf("Copy was aborted: %s", getResult.CopyStatusDescription)
case Failed:
return fmt.Errorf("Copy failed: %s", getResult.CopyStatusDescription)
case Success:
return nil
case Pending:
time.Sleep(pollingInterval)
continue
}
}
return fmt.Errorf("Unexpected error waiting for the copy to complete")
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/copy_test.go 0000664 0000000 0000000 00000012636 14232154237 0022506 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCopyFromExistingFile(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
copiedFileName := "copied.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Duplicating that file..")
copiedInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetBlobEndpoint(blobClient.BaseURI, accountName), containerName, fileName),
}
if err := blobClient.CopyAndWait(ctx, accountName, containerName, copiedFileName, copiedInput, refreshInterval); err != nil {
t.Fatalf("Error duplicating file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Original File..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the original file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Copied File..")
copiedProps, err := blobClient.GetProperties(ctx, accountName, containerName, copiedFileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the copied file: %s", err)
}
if props.ContentLength != copiedProps.ContentLength {
t.Fatalf("Expected the content length to be %d but it was %d", props.ContentLength, copiedProps.ContentLength)
}
t.Logf("[DEBUG] Deleting copied file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, copiedFileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
t.Logf("[DEBUG] Deleting original file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
func TestCopyFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
if props.ContentLength == 0 {
t.Fatalf("Expected the file to be there but looks like it isn't: %d", props.ContentLength)
}
t.Logf("[DEBUG] Deleting file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/delete.go 0000664 0000000 0000000 00000007057 14232154237 0021740 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteInput struct {
// Should any Snapshots for this Blob also be deleted?
// If the Blob has Snapshots and this is set to False a 409 Conflict will be returned
DeleteSnapshots bool
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// Delete marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`blobName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.DeleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/delete_snapshot.go 0000664 0000000 0000000 00000007675 14232154237 0023665 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The DateTime of the Snapshot which should be marked for Deletion
SnapshotDateTime string
}
// DeleteSnapshot marks a single Snapshot of a Blob for Deletion based on it's DateTime, which will be deleted during the next Garbage Collection cycle.
func (client Client) DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`blobName` cannot be an empty string.")
}
if input.SnapshotDateTime == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`input.SnapshotDateTime` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotDateTime),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/delete_snapshots.go 0000664 0000000 0000000 00000007161 14232154237 0024036 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotsInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// DeleteSnapshots marks all Snapshots of a Blob for Deletion, which will be deleted during the next Garbage Collection Cycle.
func (client Client) DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`blobName` cannot be an empty string.")
}
req, err := client.DeleteSnapshotsPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotsPreparer prepares the DeleteSnapshots request.
func (client Client) DeleteSnapshotsPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// only delete the snapshots but leave the blob as-is
"x-ms-delete-snapshots": "only",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotsSender sends the DeleteSnapshots request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotsResponder handles the response to the DeleteSnapshots request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/get.go 0000664 0000000 0000000 00000007552 14232154237 0021255 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetResult struct {
autorest.Response
Contents []byte
}
// Get reads or downloads a blob from the system, including its metadata and properties.
func (client Client) Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Get", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Get", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Get", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Get", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "Get", "`input.LeaseID` should either be specified or nil, not an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "Get", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, containerName, blobName string, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil {
result.Contents = make([]byte, resp.ContentLength)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/get_block_list.go 0000664 0000000 0000000 00000010765 14232154237 0023462 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetBlockListInput struct {
BlockListType BlockListType
LeaseID *string
}
type GetBlockListResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
// A list of blocks which have been committed
CommittedBlocks CommittedBlocks `xml:"CommittedBlocks,omitempty"`
// A list of blocks which have not yet been committed
UncommittedBlocks UncommittedBlocks `xml:"UncommittedBlocks,omitempty"`
}
// GetBlockList retrieves the list of blocks that have been uploaded as part of a block blob.
func (client Client) GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.GetBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", nil, "Failure preparing request")
return
}
resp, err := client.GetBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure sending request")
return
}
result, err = client.GetBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure responding to request")
return
}
return
}
// GetBlockListPreparer prepares the GetBlockList request.
func (client Client) GetBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"blocklisttype": autorest.Encode("query", string(input.BlockListType)),
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetBlockListSender sends the GetBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetBlockListResponder handles the response to the GetBlockList request. The method always
// closes the http.Response Body.
func (client Client) GetBlockListResponder(resp *http.Response) (result GetBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/get_page_ranges.go 0000664 0000000 0000000 00000011500 14232154237 0023574 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPageRangesInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetPageRangesResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
PageRanges []PageRange `xml:"PageRange"`
}
type PageRange struct {
// The start byte offset for this range, inclusive
Start int64 `xml:"Start"`
// The end byte offset for this range, inclusive
End int64 `xml:"End"`
}
// GetPageRanges returns the list of valid page ranges for a page blob or snapshot of a page blob.
func (client Client) GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`blobName` cannot be an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPageRangesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", nil, "Failure preparing request")
return
}
resp, err := client.GetPageRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure sending request")
return
}
result, err = client.GetPageRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure responding to request")
return
}
return
}
// GetPageRangesPreparer prepares the GetPageRanges request.
func (client Client) GetPageRangesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "pagelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPageRangesSender sends the GetPageRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPageRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPageRangesResponder handles the response to the GetPageRanges request. The method always
// closes the http.Response Body.
func (client Client) GetPageRangesResponder(resp *http.Response) (result GetPageRangesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/incremental_copy_blob.go 0000664 0000000 0000000 00000010703 14232154237 0025017 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type IncrementalCopyBlobInput struct {
CopySource string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
}
// IncrementalCopyBlob 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.
func (client Client) IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`input.CopySource` cannot be an empty string.")
}
req, err := client.IncrementalCopyBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", nil, "Failure preparing request")
return
}
resp, err := client.IncrementalCopyBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure sending request")
return
}
result, err = client.IncrementalCopyBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure responding to request")
return
}
return
}
// IncrementalCopyBlobPreparer prepares the IncrementalCopyBlob request.
func (client Client) IncrementalCopyBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "incrementalcopy"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// IncrementalCopyBlobSender sends the IncrementalCopyBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) IncrementalCopyBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// IncrementalCopyBlobResponder handles the response to the IncrementalCopyBlob request. The method always
// closes the http.Response Body.
func (client Client) IncrementalCopyBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/lease_acquire.go 0000664 0000000 0000000 00000011502 14232154237 0023266 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput struct {
// The ID of the existing Lease, if leased
LeaseID *string
// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires.
// A non-infinite lease can be between 15 and 60 seconds
LeaseDuration int
// The Proposed new ID for the Lease
ProposedLeaseID *string
}
type AcquireLeaseResult struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a blob for write and delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseID` cannot be an empty string, if specified.")
}
if input.ProposedLeaseID != nil && *input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.ProposedLeaseID` cannot be an empty string, if specified.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.ProposedLeaseID != nil {
headers["x-ms-proposed-lease-id"] = input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResult, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/lease_break.go 0000664 0000000 0000000 00000010614 14232154237 0022724 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks an existing lock on a blob using the LeaseID.
func (client Client) BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/lease_change.go 0000664 0000000 0000000 00000007777 14232154237 0023105 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes an existing lock on a blob for another lock.
func (client Client) ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`blobName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/lease_release.go 0000664 0000000 0000000 00000006720 14232154237 0023263 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases a lock based on the Lease ID.
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/lease_renew.go 0000664 0000000 0000000 00000006555 14232154237 0022771 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
func (client Client) RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/lease_test.go 0000664 0000000 0000000 00000007147 14232154237 0022626 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLeaseLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
defer blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{})
// Test begins here
t.Logf("[DEBUG] Acquiring Lease..")
leaseInput := AcquireLeaseInput{
LeaseDuration: -1,
}
leaseInfo, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Changing Lease..")
changeLeaseInput := ChangeLeaseInput{
ExistingLeaseID: leaseInfo.LeaseID,
ProposedLeaseID: "31f5bb01-cdd9-4166-bcdc-95186076bde0",
}
changeLeaseResult, err := blobClient.ChangeLease(ctx, accountName, containerName, fileName, changeLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
t.Logf("[DEBUG] New Lease ID: %q", changeLeaseResult.LeaseID)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, changeLeaseResult.LeaseID); err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Acquiring a new lease..")
leaseInput = AcquireLeaseInput{
LeaseDuration: 30,
}
leaseInfo, err = blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Renewing lease..")
if _, err := blobClient.RenewLease(ctx, accountName, containerName, fileName, leaseInfo.LeaseID); err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
t.Logf("[DEBUG] Breaking lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseInfo.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/lifecycle_test.go 0000664 0000000 0000000 00000012554 14232154237 0023472 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Blob Properties..")
details, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 0 {
t.Fatalf("Expected there to be no items of metadata but got %d", len(details.MetaData))
}
t.Logf("[DEBUG] Checking it's returned in the List API..")
listInput := containers.ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 1 {
t.Fatalf("Expected there to be 1 blob in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Setting MetaData..")
metaDataInput := SetMetaDataInput{
MetaData: map[string]string{
"hello": "there",
},
}
if _, err := blobClient.SetMetaData(ctx, accountName, containerName, fileName, metaDataInput); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 1 {
t.Fatalf("Expected there to be 1 item of metadata but got %d", len(details.MetaData))
}
if details.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", details.MetaData["there"])
}
t.Logf("[DEBUG] Retrieving the Block List..")
getBlockListInput := GetBlockListInput{
BlockListType: All,
}
blockList, err := blobClient.GetBlockList(ctx, accountName, containerName, fileName, getBlockListInput)
if err != nil {
t.Fatalf("Error retrieving Block List: %s", err)
}
// since this is a copy from an existing file, all blocks should be present
if len(blockList.CommittedBlocks.Blocks) == 0 {
t.Fatalf("Expected there to be committed blocks but there weren't!")
}
if len(blockList.UncommittedBlocks.Blocks) != 0 {
t.Fatalf("Expected all blocks to be committed but got %d uncommitted blocks", len(blockList.UncommittedBlocks.Blocks))
}
t.Logf("[DEBUG] Changing the Access Tiers..")
tiers := []AccessTier{
Hot,
Cool,
Archive,
}
for _, tier := range tiers {
t.Logf("[DEBUG] Updating the Access Tier to %q..", string(tier))
if _, err := blobClient.SetTier(ctx, accountName, containerName, fileName, tier); err != nil {
t.Fatalf("Error setting the Access Tier: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
if details.AccessTier != tier {
t.Fatalf("Expected the AccessTier to be %q but got %q", tier, details.AccessTier)
}
}
t.Logf("[DEBUG] Deleting Blob")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/metadata_set.go 0000664 0000000 0000000 00000007724 14232154237 0023132 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SetMetaDataInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// Any metadata which should be added to this blob
MetaData map[string]string
}
// SetMetaData marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "GetProperties", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/models.go 0000664 0000000 0000000 00000002714 14232154237 0021754 0 ustar 00root root 0000000 0000000 package blobs
type AccessTier string
var (
Archive AccessTier = "Archive"
Cool AccessTier = "Cool"
Hot AccessTier = "Hot"
)
type ArchiveStatus string
var (
None ArchiveStatus = ""
RehydratePendingToCool ArchiveStatus = "rehydrate-pending-to-cool"
RehydratePendingToHot ArchiveStatus = "rehydrate-pending-to-hot"
)
type BlockListType string
var (
All BlockListType = "all"
Committed BlockListType = "committed"
Uncommitted BlockListType = "uncommitted"
)
type Block struct {
// The base64-encoded Block ID
Name string `xml:"Name"`
// The size of the Block in Bytes
Size int64 `xml:"Size"`
}
type BlobType string
var (
AppendBlob BlobType = "AppendBlob"
BlockBlob BlobType = "BlockBlob"
PageBlob BlobType = "PageBlob"
)
type CommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
type CopyStatus string
var (
Aborted CopyStatus = "aborted"
Failed CopyStatus = "failed"
Pending CopyStatus = "pending"
Success CopyStatus = "success"
)
type LeaseDuration string
var (
Fixed LeaseDuration = "fixed"
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
type UncommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/properties_get.go 0000664 0000000 0000000 00000031314 14232154237 0023522 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
type GetPropertiesResult struct {
autorest.Response
// The tier of page blob on a premium storage account or tier of block blob on blob storage or general purpose v2 account.
AccessTier AccessTier
// This gives the last time tier was changed on the object.
// This header is returned only if tier on block blob was ever set.
// The date format follows RFC 1123
AccessTierChangeTime string
// For page blobs on a premium storage account only.
// If the access tier is not explicitly set on the blob, the tier is inferred based on its content length
// and this header will be returned with true value.
// For block blobs on Blob Storage or general purpose v2 account, if the blob does not have the access tier
// set then we infer the tier from the storage account properties. This header is set only if the block blob
// tier is inferred
AccessTierInferred bool
// For blob storage or general purpose v2 account.
// If the blob is being rehydrated and is not complete then this header is returned indicating
// that rehydrate is pending and also tells the destination tier
ArchiveStatus ArchiveStatus
// The number of committed blocks present in the blob.
// This header is returned only for append blobs.
BlobCommittedBlockCount string
// The current sequence number for a page blob.
// This header is not returned for block blobs or append blobs.
// This header is not returned for block blobs.
BlobSequenceNumber string
// The blob type.
BlobType BlobType
// If the Cache-Control request header has previously been set for the blob, that value is returned in this header.
CacheControl string
// The Content-Disposition response header field conveys additional information about how to process
// the response payload, and also can be used to attach additional metadata.
// For example, if set to attachment, it indicates that the user-agent should not display the response,
// but instead show a Save As dialog.
ContentDisposition string
// If the Content-Encoding request header has previously been set for the blob,
// that value is returned in this header.
ContentEncoding string
// If the Content-Language request header has previously been set for the blob,
// that value is returned in this header.
ContentLanguage string
// The size of the blob in bytes.
// For a page blob, this header returns the value of the x-ms-blob-content-length header stored with the blob.
ContentLength int64
// The content type specified for the blob.
// If no content type was specified, the default content type is `application/octet-stream`.
ContentType string
// If the Content-MD5 header has been set for the blob, this response header is returned so that
// the client can check for message content integrity.
ContentMD5 string
// Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob.
// This value can specify the time of a completed, aborted, or failed copy attempt.
// This header does not appear if a copy is pending, if this blob has never been the
// destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob
// operation using Set Blob Properties, Put Blob, or Put Block List.
CopyCompletionTime string
// Included if the blob is incremental copy blob or incremental copy snapshot, if x-ms-copy-status is success.
// Snapshot time of the last successful incremental copy snapshot for this blob
CopyDestinationSnapshot string
// String identifier for the last attempted Copy Blob operation where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyID string
// Contains the number of bytes copied and the total bytes in the source in the last attempted
// Copy Blob operation where this blob was the destination blob.
// Can show between 0 and Content-Length bytes copied.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyProgress string
// URL up to 2 KB in length that specifies the source blob used in the last attempted Copy Blob operation
// where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List
CopySource string
// State of the copy operation identified by x-ms-copy-id, with these values:
// - success: Copy completed successfully.
// - pending: Copy is in progress.
// Check x-ms-copy-status-description if intermittent, non-fatal errors
// impede copy progress but don’t cause failure.
// - aborted: Copy was ended by Abort Copy Blob.
// - failed: Copy failed. See x-ms- copy-status-description for failure details.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a completed Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatus CopyStatus
// Describes cause of fatal or non-fatal copy operation failure.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatusDescription string
// The date/time at which the blob was created. The date format follows RFC 1123
CreationTime string
// The ETag contains a value that you can use to perform operations conditionally
ETag string
// Included if the blob is incremental copy blob.
IncrementalCopy bool
// The date/time that the blob was last modified. The date format follows RFC 1123.
LastModified string
// When a blob is leased, specifies whether the lease is of infinite or fixed duration
LeaseDuration LeaseDuration
// The lease state of the blob
LeaseState LeaseState
LeaseStatus LeaseStatus
// A set of name-value pairs that correspond to the user-defined metadata associated with this blob
MetaData map[string]string
// Is the Storage Account encrypted using server-side encryption? This should always return true
ServerEncrypted bool
}
// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the blob
func (client Client) GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.AccessTier = AccessTier(resp.Header.Get("x-ms-access-tier"))
result.AccessTierChangeTime = resp.Header.Get(" x-ms-access-tier-change-time")
result.ArchiveStatus = ArchiveStatus(resp.Header.Get(" x-ms-archive-status"))
result.BlobCommittedBlockCount = resp.Header.Get("x-ms-blob-committed-block-count")
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.BlobType = BlobType(resp.Header.Get("x-ms-blob-type"))
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.CopyDestinationSnapshot = resp.Header.Get("x-ms-copy-destination-snapshot")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = CopyStatus(resp.Header.Get("x-ms-copy-status"))
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CreationTime = resp.Header.Get("x-ms-creation-time")
result.ETag = resp.Header.Get("Etag")
result.LastModified = resp.Header.Get("Last-Modified")
result.LeaseDuration = LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.MetaData = metadata.ParseFromHeaders(resp.Header)
if v := resp.Header.Get("x-ms-access-tier-inferred"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.AccessTierInferred = b
}
if v := resp.Header.Get("Content-Length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
}
result.ContentLength = int64(i)
}
if v := resp.Header.Get("x-ms-incremental-copy"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
if v := resp.Header.Get("x-ms-server-encrypted"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/properties_set.go 0000664 0000000 0000000 00000012111 14232154237 0023530 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
CacheControl *string
ContentType *string
ContentMD5 *string
ContentEncoding *string
ContentLanguage *string
LeaseID *string
ContentDisposition *string
ContentLength *int64
SequenceNumberAction *SequenceNumberAction
BlobSequenceNumber *string
}
type SetPropertiesResult struct {
autorest.Response
BlobSequenceNumber string
Etag string
}
// SetProperties sets system properties on the blob.
func (client Client) SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
type SequenceNumberAction string
var (
Increment SequenceNumberAction = "increment"
Max SequenceNumberAction = "max"
Update SequenceNumberAction = "update"
)
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.ContentLength != nil {
headers["x-ms-blob-content-length"] = *input.ContentLength
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SequenceNumberAction != nil {
headers["x-ms-sequence-number-action"] = string(*input.SequenceNumberAction)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result SetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.Etag = resp.Header.Get("Etag")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_append_blob.go 0000664 0000000 0000000 00000011323 14232154237 0023622 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutAppendBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutAppendBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new append blob, or updates the content of an existing blob.
func (client Client) PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutAppendBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutAppendBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutAppendBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure sending request")
return
}
result, err = client.PutAppendBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure responding to request")
return
}
return
}
// PutAppendBlobPreparer prepares the PutAppendBlob request.
func (client Client) PutAppendBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(AppendBlob),
"x-ms-version": APIVersion,
// For a page blob or an append blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutAppendBlobSender sends the PutAppendBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutAppendBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutAppendBlobResponder handles the response to the PutAppendBlob request. The method always
// closes the http.Response Body.
func (client Client) PutAppendBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_block.go 0000664 0000000 0000000 00000010100 14232154237 0022437 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockInput struct {
BlockID string
Content []byte
ContentMD5 *string
LeaseID *string
}
type PutBlockResult struct {
autorest.Response
ContentMD5 string
}
// PutBlock creates a new block to be committed as part of a blob.
func (client Client) PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.BlockID` cannot be an empty string.")
}
if len(input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.Content` cannot be empty.")
}
req, err := client.PutBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure sending request")
return
}
result, err = client.PutBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure responding to request")
return
}
return
}
// PutBlockPreparer prepares the PutBlock request.
func (client Client) PutBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Content-Length": int(len(input.Content)),
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockSender sends the PutBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockResponder handles the response to the PutBlock request. The method always
// closes the http.Response Body.
func (client Client) PutBlockResponder(resp *http.Response) (result PutBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_block_blob.go 0000664 0000000 0000000 00000011750 14232154237 0023451 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutBlockBlobInput struct {
CacheControl *string
Content *[]byte
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutBlockBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block append blob, or updates the content of an existing block blob.
func (client Client) PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`input.Content` must either be nil or not empty.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutBlockBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutBlockBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure sending request")
return
}
result, err = client.PutBlockBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure responding to request")
return
}
return
}
// PutBlockBlobPreparer prepares the PutBlockBlob request.
func (client Client) PutBlockBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(BlockBlob),
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockBlobSender sends the PutBlockBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockBlobResponder handles the response to the PutBlockBlob request. The method always
// closes the http.Response Body.
func (client Client) PutBlockBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_block_blob_file.go 0000664 0000000 0000000 00000001510 14232154237 0024441 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"io"
"os"
)
// PutBlockBlobFromFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
bytes := make([]byte, fileSize)
_, err = file.ReadAt(bytes, 0)
if err != nil {
if err != io.EOF {
return fmt.Errorf("Error reading bytes: %s", err)
}
}
input.Content = &bytes
if _, err = client.PutBlockBlob(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error putting bytes: %s", err)
}
return nil
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_block_list.go 0000664 0000000 0000000 00000012220 14232154237 0023477 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type BlockList struct {
CommittedBlockIDs []BlockID `xml:"Committed,omitempty"`
UncommittedBlockIDs []BlockID `xml:"Uncommitted,omitempty"`
LatestBlockIDs []BlockID `xml:"Latest,omitempty"`
}
type BlockID struct {
Value string `xml:",chardata"`
}
type PutBlockListInput struct {
BlockList BlockList
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
MetaData map[string]string
LeaseID *string
}
type PutBlockListResult struct {
autorest.Response
ContentMD5 string
ETag string
LastModified string
}
// PutBlockList 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.
func (client Client) PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.PutBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure sending request")
return
}
result, err = client.PutBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure responding to request")
return
}
return
}
// PutBlockListPreparer prepares the PutBlockList request.
func (client Client) PutBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(input.BlockList))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockListSender sends the PutBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockListResponder handles the response to the PutBlockList request. The method always
// closes the http.Response Body.
func (client Client) PutBlockListResponder(resp *http.Response) (result PutBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_page_blob.go 0000664 0000000 0000000 00000012264 14232154237 0023274 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutPageBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
BlobContentLengthBytes int64
BlobSequenceNumber *int64
AccessTier *AccessTier
}
// PutPageBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block blob, or updates the content of an existing page blob.
func (client Client) PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`blobName` cannot be an empty string.")
}
if input.BlobContentLengthBytes == 0 || input.BlobContentLengthBytes%512 != 0 {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`input.BlobContentLengthBytes` must be aligned to a 512-byte boundary.")
}
req, err := client.PutPageBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutPageBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure sending request")
return
}
result, err = client.PutPageBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure responding to request")
return
}
return
}
// PutPageBlobPreparer prepares the PutPageBlob request.
func (client Client) PutPageBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(PageBlob),
"x-ms-version": APIVersion,
// For a page blob or an page blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
// This header specifies the maximum size for the page blob, up to 8 TB.
// The page blob size must be aligned to a 512-byte boundary.
"x-ms-blob-content-length": input.BlobContentLengthBytes,
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageBlobSender sends the PutPageBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageBlobResponder handles the response to the PutPageBlob request. The method always
// closes the http.Response Body.
func (client Client) PutPageBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_page_clear.go 0000664 0000000 0000000 00000007556 14232154237 0023454 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageClearInput struct {
StartByte int64
EndByte int64
LeaseID *string
}
// PutPageClear clears a range of pages within a page blob.
func (client Client) PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.EndByte` must be greater than 0.")
}
req, err := client.PutPageClearPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", nil, "Failure preparing request")
return
}
resp, err := client.PutPageClearSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure sending request")
return
}
result, err = client.PutPageClearResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure responding to request")
return
}
return
}
// PutPageClearPreparer prepares the PutPageClear request.
func (client Client) PutPageClearPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageClearSender sends the PutPageClear request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageClearSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageClearResponder handles the response to the PutPageClear request. The method always
// closes the http.Response Body.
func (client Client) PutPageClearResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/put_page_update.go 0000664 0000000 0000000 00000012777 14232154237 0023651 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageUpdateInput struct {
StartByte int64
EndByte int64
Content []byte
IfSequenceNumberEQ *string
IfSequenceNumberLE *string
IfSequenceNumberLT *string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
LeaseID *string
}
type PutPageUpdateResult struct {
autorest.Response
BlobSequenceNumber string
ContentMD5 string
LastModified string
}
// PutPageUpdate writes a range of pages to a page blob.
func (client Client) PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.EndByte` must be greater than 0.")
}
expectedSize := (input.EndByte - input.StartByte) + 1
actualSize := int64(len(input.Content))
if expectedSize != actualSize {
return result, validation.NewError("blobs.Client", "PutPageUpdate", fmt.Sprintf("Content Size was defined as %d but got %d.", expectedSize, actualSize))
}
req, err := client.PutPageUpdatePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", nil, "Failure preparing request")
return
}
resp, err := client.PutPageUpdateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure sending request")
return
}
result, err = client.PutPageUpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure responding to request")
return
}
return
}
// PutPageUpdatePreparer prepares the PutPageUpdate request.
func (client Client) PutPageUpdatePreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
"Content-Length": int(len(input.Content)),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfSequenceNumberEQ != nil {
headers["x-ms-if-sequence-number-eq"] = *input.IfSequenceNumberEQ
}
if input.IfSequenceNumberLE != nil {
headers["x-ms-if-sequence-number-le"] = *input.IfSequenceNumberLE
}
if input.IfSequenceNumberLT != nil {
headers["x-ms-if-sequence-number-lt"] = *input.IfSequenceNumberLT
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageUpdateSender sends the PutPageUpdate request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageUpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageUpdateResponder handles the response to the PutPageUpdate request. The method always
// closes the http.Response Body.
func (client Client) PutPageUpdateResponder(resp *http.Response) (result PutPageUpdateResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/resource_id.go 0000664 0000000 0000000 00000003060 14232154237 0022767 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Blob
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName, blobName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, containerName, blobName)
}
type ResourceID struct {
AccountName string
ContainerName string
BlobName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Blob Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar/example.vhd
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
containerName := segments[0]
blobName := strings.TrimPrefix(path, containerName)
blobName = strings.TrimPrefix(blobName, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
BlobName: blobName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/resource_id_test.go 0000664 0000000 0000000 00000006670 14232154237 0024040 0 ustar 00root root 0000000 0000000 package blobs
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1", "blob1.vhd")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "blob1.vhd" {
t.Fatalf("Expected Blob Name to be `blob1.vhd` but got %q", actual.BlobName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/example/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/example/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/example/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/example/blob1.vhd",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "example/blob1.vhd" {
t.Fatalf("Expected Blob Name to be `example/blob1.vhd` but got %q", actual.BlobName)
}
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/set_tier.go 0000664 0000000 0000000 00000006325 14232154237 0022311 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetTier sets the tier on a blob.
func (client Client) SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`blobName` cannot be an empty string.")
}
req, err := client.SetTierPreparer(ctx, accountName, containerName, blobName, tier)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", nil, "Failure preparing request")
return
}
resp, err := client.SetTierSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure sending request")
return
}
result, err = client.SetTierResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure responding to request")
return
}
return
}
// SetTierPreparer prepares the SetTier request.
func (client Client) SetTierPreparer(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "tier"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-access-tier": string(tier),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetTierSender sends the SetTier request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetTierSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetTierResponder handles the response to the SetTier request. The method always
// closes the http.Response Body.
func (client Client) SetTierResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/snapshot.go 0000664 0000000 0000000 00000013463 14232154237 0022333 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// MetaData is a user-defined name-value pair associated with the blob.
// If no name-value pairs are specified, the operation will copy the base blob metadata to the snapshot.
// If one or more name-value pairs are specified, the snapshot is created with the specified metadata,
// and metadata is not copied from the base blob.
MetaData map[string]string
// A DateTime value which will only snapshot the blob if it has been modified since the specified date/time
// If the base blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value which will only snapshot the blob if it has not been modified since the specified date/time
// If the base blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value to snapshot the blob only if its ETag value matches the value specified.
// If the values do not match, the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value for this conditional header to snapshot the blob only if its ETag value
// does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
}
type SnapshotResult struct {
autorest.Response
// The ETag of the snapshot
ETag string
// A DateTime value that uniquely identifies the snapshot.
// The value of this header indicates the snapshot version,
// and may be used in subsequent requests to access the snapshot.
SnapshotDateTime string
}
// Snapshot captures a Snapshot of a given Blob
func (client Client) Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "Snapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", nil, "Failure preparing request")
return
}
resp, err := client.SnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure sending request")
return
}
result, err = client.SnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure responding to request")
return
}
return
}
// SnapshotPreparer prepares the Snapshot request.
func (client Client) SnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SnapshotSender sends the Snapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SnapshotResponder handles the response to the Snapshot request. The method always
// closes the http.Response Body.
func (client Client) SnapshotResponder(resp *http.Response) (result SnapshotResult, err error) {
if resp != nil && resp.Header != nil {
result.ETag = resp.Header.Get("ETag")
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/snapshot_get_properties.go 0000664 0000000 0000000 00000006445 14232154237 0025450 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetSnapshotPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The ID of the Snapshot which should be retrieved
SnapshotID string
}
// GetSnapshotProperties returns all user-defined metadata, standard HTTP properties, and system properties for
// the specified snapshot of a blob
func (client Client) GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`blobName` cannot be an empty string.")
}
if input.SnapshotID == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`input.SnapshotID` cannot be an empty string.")
}
req, err := client.GetSnapshotPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", nil, "Failure preparing request")
return
}
// we re-use the GetProperties methods since this is otherwise the same
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/snapshot_test.go 0000664 0000000 0000000 00000013406 14232154237 0023367 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestSnapshotLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatalf("Error creating: %s", err)
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] First Snapshot..")
firstSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{})
if err != nil {
t.Fatalf("Error taking first snapshot: %s", err)
}
t.Logf("[DEBUG] First Snapshot ID: %q", firstSnapshot.SnapshotDateTime)
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
t.Logf("[DEBUG] Second Snapshot..")
secondSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
MetaData: map[string]string{
"hello": "world",
},
})
if err != nil {
t.Fatalf("Error taking Second snapshot: %s", err)
}
t.Logf("[DEBUG] Second Snapshot ID: %q", secondSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Leasing the Blob..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
// infinite
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error leasing Blob: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Third Snapshot..")
thirdSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error taking Third snapshot: %s", err)
}
t.Logf("[DEBUG] Third Snapshot ID: %q", thirdSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, leaseDetails.LeaseID); err != nil {
t.Fatalf("Error releasing Lease: %s", err)
}
// get the properties from the blob, which should include the LastModifiedDate
t.Logf("[DEBUG] Retrieving Properties for Blob")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
// confirm that the If-Modified-None returns an error
t.Logf("[DEBUG] Third Snapshot..")
fourthSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
IfModifiedSince: &props.LastModified,
})
if err == nil {
t.Fatalf("Expected an error but didn't get one")
}
if fourthSnapshot.Response.StatusCode != http.StatusPreconditionFailed {
t.Fatalf("Expected the status code to be Precondition Failed but got: %d", fourthSnapshot.Response.StatusCode)
}
t.Logf("[DEBUG] Retrieving the Second Snapshot Properties..")
getSecondSnapshotInput := GetSnapshotPropertiesInput{
SnapshotID: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput); err != nil {
t.Fatalf("Error retrieving properties for the second snapshot: %s", err)
}
t.Logf("[DEBUG] Deleting the Second Snapshot..")
deleteSnapshotInput := DeleteSnapshotInput{
SnapshotDateTime: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.DeleteSnapshot(ctx, accountName, containerName, fileName, deleteSnapshotInput); err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Second Snapshot Properties..")
secondSnapshotProps, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput)
if err == nil {
t.Fatalf("Expected an error retrieving the snapshot but got none")
}
if secondSnapshotProps.Response.StatusCode != http.StatusNotFound {
t.Fatalf("Expected the status code to be %d but got %q", http.StatusNoContent, secondSnapshotProps.Response.StatusCode)
}
t.Logf("[DEBUG] Deleting all the snapshots..")
if _, err := blobClient.DeleteSnapshots(ctx, accountName, containerName, fileName, DeleteSnapshotsInput{}); err != nil {
t.Fatalf("Error deleting snapshots: %s", err)
}
t.Logf("[DEBUG] Deleting the Blob..")
deleteInput := DeleteInput{
DeleteSnapshots: false,
}
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, deleteInput); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/undelete.go 0000664 0000000 0000000 00000006323 14232154237 0022276 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Undelete restores the contents and metadata of soft deleted blob and any associated soft deleted snapshots.
func (client Client) Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`blobName` cannot be an empty string.")
}
req, err := client.UndeletePreparer(ctx, accountName, containerName, blobName)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", nil, "Failure preparing request")
return
}
resp, err := client.UndeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure sending request")
return
}
result, err = client.UndeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure responding to request")
return
}
return
}
// UndeletePreparer prepares the Undelete request.
func (client Client) UndeletePreparer(ctx context.Context, accountName, containerName, blobName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "undelete"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UndeleteSender sends the Undelete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UndeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UndeleteResponder handles the response to the Undelete request. The method always
// closes the http.Response Body.
func (client Client) UndeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/blobs/version.go 0000664 0000000 0000000 00000000463 14232154237 0022155 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/ 0000775 0000000 0000000 00000000000 14232154237 0021202 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/blob/containers/README.md 0000664 0000000 0000000 00000002136 14232154237 0022463 0 ustar 00root root 0000000 0000000 ## Blob Storage Container SDK for API version 2017-07-29
This package allows you to interact with the Containers Blob Storage API
### Supported Authorizers
* SharedKeyLite (Blob, File & Queue)
Note: when using the `ListBlobs` operation, only `SharedKeyLite` authentication is supported.
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/blob/containers"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
containersClient := containers.New()
containersClient.Client.Authorizer = storageAuth
ctx := context.TODO()
createInput := containers.CreateInput{
AccessLevel: containers.Private,
}
if _, err := containersClient.Create(ctx, accountName, containerName, createInput); err != nil {
return fmt.Errorf("Error creating Container: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/blob/containers/client.go 0000664 0000000 0000000 00000001632 14232154237 0023011 0 ustar 00root root 0000000 0000000 package containers
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Containers.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
func (client Client) setAccessLevelIntoHeaders(headers map[string]interface{}, level AccessLevel) map[string]interface{} {
// If this header is not included in the request, container data is private to the account owner.
if level != Private {
headers["x-ms-blob-public-access"] = string(level)
}
return headers
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/create.go 0000664 0000000 0000000 00000010233 14232154237 0022773 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies whether data in the container may be accessed publicly and the level of access
AccessLevel AccessLevel
// A name-value pair to associate with the container as metadata.
MetaData map[string]string
}
type CreateResponse struct {
autorest.Response
Error *ErrorResponse `xml:"Error"`
}
// Create creates a new container under the specified account.
// If the container with the same name already exists, the operation fails.
func (client Client) Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Create", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Create", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("containers.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, containerName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, input.AccessLevel)
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result CreateResponse, err error) {
successfulStatusCodes := []int{
http.StatusCreated,
}
if autorest.ResponseHasStatusCode(resp, successfulStatusCodes...) {
// when successful there's no response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
} else {
// however when there's an error the error's in the response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/delete.go 0000664 0000000 0000000 00000005600 14232154237 0022774 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete marks the specified container for deletion.
// The container and any blobs contained within it are later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Delete", "`containerName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, containerName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/get_properties.go 0000664 0000000 0000000 00000011677 14232154237 0024600 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// GetProperties returns the properties for this Container without a Lease
func (client Client) GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error) {
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
return client.GetPropertiesWithLeaseID(ctx, accountName, containerName, "")
}
// GetPropertiesWithLeaseID returns the properties for this Container using the specified LeaseID
func (client Client) GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`containerName` cannot be an empty string.")
}
req, err := client.GetPropertiesWithLeaseIDPreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesWithLeaseIDSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesWithLeaseIDPreparer prepares the GetPropertiesWithLeaseID request.
func (client Client) GetPropertiesWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesWithLeaseIDSender sends the GetPropertiesWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesWithLeaseIDResponder handles the response to the GetPropertiesWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesWithLeaseIDResponder(resp *http.Response) (result ContainerProperties, err error) {
if resp != nil {
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
if result.LeaseStatus == Locked {
duration := LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseDuration = &duration
}
// If this header is not returned in the response, the container is private to the account owner.
accessLevel := resp.Header.Get("x-ms-blob-public-access")
if accessLevel != "" {
result.AccessLevel = AccessLevel(accessLevel)
} else {
result.AccessLevel = Private
}
// we can't necessarily use strconv.ParseBool here since this could be nil (only in some API versions)
result.HasImmutabilityPolicy = strings.EqualFold(resp.Header.Get("x-ms-has-immutability-policy"), "true")
result.HasLegalHold = strings.EqualFold(resp.Header.Get("x-ms-has-legal-hold"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/lease_acquire.go 0000664 0000000 0000000 00000007762 14232154237 0024347 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput 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
LeaseDuration int
ProposedLeaseID string
}
type AcquireLeaseResponse struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a container for delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("containers.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName string, containerName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.ProposedLeaseID != "" {
headers["x-ms-proposed-lease-id"] = input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/lease_break.go 0000664 0000000 0000000 00000010521 14232154237 0023765 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strconv"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks a lock based on it's Lease ID
func (client Client) BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName string, containerName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result BreakLeaseResponse, err error) {
if resp != nil {
leaseRaw := resp.Header.Get("x-ms-lease-time")
if leaseRaw != "" {
i, err := strconv.Atoi(leaseRaw)
if err == nil {
result.LeaseTime = i
}
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/lease_change.go 0000664 0000000 0000000 00000007356 14232154237 0024142 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes the lock from one Lease ID to another Lease ID
func (client Client) ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName string, containerName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/lease_release.go 0000664 0000000 0000000 00000006324 14232154237 0024327 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases the lock based on the Lease ID
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/lease_renew.go 0000664 0000000 0000000 00000006251 14232154237 0024026 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// RenewLease renewes the lock based on the Lease ID
func (client Client) RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/lifecycle_test.go 0000664 0000000 0000000 00000013057 14232154237 0024535 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
// first let's test an empty container
input := CreateInput{}
_, err = containersClient.Create(ctx, accountName, containerName, input)
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
container, err := containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error retrieving: %s", err))
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if len(container.MetaData) != 0 {
t.Fatalf("Expected MetaData to be empty but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the metadata
metaData := map[string]string{
"dont": "kill-my-vibe",
}
_, err = containersClient.SetMetaData(ctx, accountName, containerName, metaData)
if err != nil {
t.Fatal(fmt.Errorf("Error updating metadata: %s", err))
}
// give azure time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.MetaData["dont"] != "kill-my-vibe" {
t.Fatalf("Expected `kill-my-vibe` but got %q", container.MetaData["dont"])
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the ACL
_, err = containersClient.SetAccessControl(ctx, accountName, containerName, Blob)
if err != nil {
t.Fatal(fmt.Errorf("Error updating ACL's: %s", err))
}
// give azure some time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if container.AccessLevel != Blob {
t.Fatalf("Expected Access Level to be Blob but got %q", container.AccessLevel)
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// acquire a lease for 30s
acquireLeaseInput := AcquireLeaseInput{
LeaseDuration: 30,
}
acquireLeaseResp, err := containersClient.AcquireLease(ctx, accountName, containerName, acquireLeaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %s", acquireLeaseResp.LeaseID)
// we should then be able to update the ID
t.Logf("[DEBUG] Changing lease..")
updateLeaseInput := ChangeLeaseInput{
ExistingLeaseID: acquireLeaseResp.LeaseID,
ProposedLeaseID: "aaaabbbb-aaaa-bbbb-cccc-aaaabbbbcccc",
}
updateLeaseResp, err := containersClient.ChangeLease(ctx, accountName, containerName, updateLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
// then renew it
_, err = containersClient.RenewLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
// and then give it a timeout
breakPeriod := 20
breakLeaseInput := BreakLeaseInput{
LeaseID: updateLeaseResp.LeaseID,
BreakPeriod: &breakPeriod,
}
breakLeaseResp, err := containersClient.BreakLease(ctx, accountName, containerName, breakLeaseInput)
if err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
if breakLeaseResp.LeaseTime == 0 {
t.Fatalf("Lease broke immediately when should have waited: %d", breakLeaseResp.LeaseTime)
}
// and finally ditch it
_, err = containersClient.ReleaseLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Listing blobs in the container..")
listInput := ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 0 {
t.Fatalf("Expected there to be no blobs in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Deleting..")
_, err = containersClient.Delete(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/list_blobs.go 0000664 0000000 0000000 00000015033 14232154237 0023667 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListBlobsInput struct {
Delimiter *string
Include *[]Dataset
Marker *string
MaxResults *int
Prefix *string
}
type ListBlobsResult struct {
autorest.Response
Delimiter string `xml:"Delimiter"`
Marker string `xml:"Marker"`
MaxResults int `xml:"MaxResults"`
NextMarker *string `xml:"NextMarker,omitempty"`
Prefix string `xml:"Prefix"`
Blobs Blobs `xml:"Blobs"`
}
type Blobs struct {
Blobs []BlobDetails `xml:"Blob"`
BlobPrefix *BlobPrefix `xml:"BlobPrefix"`
}
type BlobDetails struct {
Name string `xml:"Name"`
Deleted bool `xml:"Deleted,omitempty"`
MetaData map[string]interface{} `map:"Metadata,omitempty"`
Properties *BlobProperties `xml:"Properties,omitempty"`
Snapshot *string `xml:"Snapshot,omitempty"`
}
type BlobProperties struct {
AccessTier *string `xml:"AccessTier,omitempty"`
AccessTierInferred *bool `xml:"AccessTierInferred,omitempty"`
AccessTierChangeTime *string `xml:"AccessTierChangeTime,omitempty"`
BlobType *string `xml:"BlobType,omitempty"`
BlobSequenceNumber *string `xml:"x-ms-blob-sequence-number,omitempty"`
CacheControl *string `xml:"Cache-Control,omitempty"`
ContentEncoding *string `xml:"ContentEncoding,omitempty"`
ContentLanguage *string `xml:"Content-Language,omitempty"`
ContentLength *int64 `xml:"Content-Length,omitempty"`
ContentMD5 *string `xml:"Content-MD5,omitempty"`
ContentType *string `xml:"Content-Type,omitempty"`
CopyCompletionTime *string `xml:"CopyCompletionTime,omitempty"`
CopyId *string `xml:"CopyId,omitempty"`
CopyStatus *string `xml:"CopyStatus,omitempty"`
CopySource *string `xml:"CopySource,omitempty"`
CopyProgress *string `xml:"CopyProgress,omitempty"`
CopyStatusDescription *string `xml:"CopyStatusDescription,omitempty"`
CreationTime *string `xml:"CreationTime,omitempty"`
ETag *string `xml:"Etag,omitempty"`
DeletedTime *string `xml:"DeletedTime,omitempty"`
IncrementalCopy *bool `xml:"IncrementalCopy,omitempty"`
LastModified *string `xml:"Last-Modified,omitempty"`
LeaseDuration *string `xml:"LeaseDuration,omitempty"`
LeaseState *string `xml:"LeaseState,omitempty"`
LeaseStatus *string `xml:"LeaseStatus,omitempty"`
RemainingRetentionDays *string `xml:"RemainingRetentionDays,omitempty"`
ServerEncrypted *bool `xml:"ServerEncrypted,omitempty"`
}
type BlobPrefix struct {
Name string `xml:"Name"`
}
// ListBlobs lists the blobs matching the specified query within the specified Container
func (client Client) ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`containerName` cannot be an empty string.")
}
if input.MaxResults != nil && (*input.MaxResults <= 0 || *input.MaxResults > 5000) {
return result, validation.NewError("containers.Client", "ListBlobs", "`input.MaxResults` can either be nil or between 0 and 5000.")
}
req, err := client.ListBlobsPreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", nil, "Failure preparing request")
return
}
resp, err := client.ListBlobsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure sending request")
return
}
result, err = client.ListBlobsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure responding to request")
return
}
return
}
// ListBlobsPreparer prepares the ListBlobs request.
func (client Client) ListBlobsPreparer(ctx context.Context, accountName, containerName string, input ListBlobsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "list"),
"restype": autorest.Encode("query", "container"),
}
if input.Delimiter != nil {
queryParameters["delimiter"] = autorest.Encode("query", *input.Delimiter)
}
if input.Include != nil {
vals := make([]string, 0)
for _, v := range *input.Include {
vals = append(vals, string(v))
}
include := strings.Join(vals, ",")
queryParameters["include"] = autorest.Encode("query", include)
}
if input.Marker != nil {
queryParameters["marker"] = autorest.Encode("query", *input.Marker)
}
if input.MaxResults != nil {
queryParameters["maxresults"] = autorest.Encode("query", *input.MaxResults)
}
if input.Prefix != nil {
queryParameters["prefix"] = autorest.Encode("query", *input.Prefix)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListBlobsSender sends the ListBlobs request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListBlobsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListBlobsResponder handles the response to the ListBlobs request. The method always
// closes the http.Response Body.
func (client Client) ListBlobsResponder(resp *http.Response) (result ListBlobsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/models.go 0000664 0000000 0000000 00000003464 14232154237 0023023 0 ustar 00root root 0000000 0000000 package containers
import "github.com/Azure/go-autorest/autorest"
type AccessLevel string
var (
// Blob specifies public read access for blobs.
// Blob data within this container can be read via anonymous request,
// but container data is not available.
// Clients cannot enumerate blobs within the container via anonymous request.
Blob AccessLevel = "blob"
// Container specifies full public read access for container and blob data.
// Clients can enumerate blobs within the container via anonymous request,
// but cannot enumerate containers within the storage account.
Container AccessLevel = "container"
// Private specifies that container data is private to the account owner
Private AccessLevel = ""
)
type ContainerProperties struct {
autorest.Response
AccessLevel AccessLevel
LeaseStatus LeaseStatus
LeaseState LeaseState
LeaseDuration *LeaseDuration
MetaData map[string]string
HasImmutabilityPolicy bool
HasLegalHold bool
}
type Dataset string
var (
Copy Dataset = "copy"
Deleted Dataset = "deleted"
MetaData Dataset = "metadata"
Snapshots Dataset = "snapshots"
UncommittedBlobs Dataset = "uncommittedblobs"
)
type ErrorResponse struct {
Code *string `xml:"Code"`
Message *string `xml:"Message"`
}
type LeaseDuration string
var (
// If this lease is for a Fixed Duration
Fixed LeaseDuration = "fixed"
// If this lease is for an Indefinite Duration
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
giovanni-0.20.0/storage/2017-07-29/blob/containers/resource_id.go 0000664 0000000 0000000 00000002341 14232154237 0024034 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Container
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, containerName)
}
type ResourceID struct {
AccountName string
ContainerName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Container Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
containerName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/resource_id_test.go 0000664 0000000 0000000 00000003765 14232154237 0025106 0 ustar 00root root 0000000 0000000 package containers
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected the container name to be `container1` but got %q", actual.ContainerName)
}
}
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/set_acl.go 0000664 0000000 0000000 00000007651 14232154237 0023154 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetAccessControl sets the Access Control for a Container without a Lease ID
func (client Client) SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error) {
return client.SetAccessControlWithLeaseID(ctx, accountName, containerName, "", level)
}
// SetAccessControlWithLeaseID sets the Access Control for a Container using the specified Lease ID
func (client Client) SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`containerName` cannot be an empty string.")
}
req, err := client.SetAccessControlWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, level)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure responding to request")
return
}
return
}
// SetAccessControlWithLeaseIDPreparer prepares the SetAccessControlWithLeaseID request.
func (client Client) SetAccessControlWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "acl"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, level)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlWithLeaseIDSender sends the SetAccessControlWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlWithLeaseIDResponder handles the response to the SetAccessControlWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/set_metadata.go 0000664 0000000 0000000 00000010137 14232154237 0024166 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the specified MetaData on the Container without a Lease ID
func (client Client) SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error) {
return client.SetMetaDataWithLeaseID(ctx, accountName, containerName, "", metaData)
}
// SetMetaDataWithLeaseID sets the specified MetaData on the Container using the specified Lease ID
func (client Client) SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("containers.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataWithLeaseIDPreparer prepares the SetMetaDataWithLeaseID request.
func (client Client) SetMetaDataWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataWithLeaseIDSender sends the SetMetaDataWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataWithLeaseIDResponder handles the response to the SetMetaDataWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/blob/containers/version.go 0000664 0000000 0000000 00000000470 14232154237 0023217 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/file/ 0000775 0000000 0000000 00000000000 14232154237 0017036 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/file/directories/ 0000775 0000000 0000000 00000000000 14232154237 0021352 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/file/directories/README.md 0000664 0000000 0000000 00000002014 14232154237 0022626 0 ustar 00root root 0000000 0000000 ## File Storage Directories SDK for API version 2017-07-29
This package allows you to interact with the Directories File Storage API
### Supported Authorizers
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/directories"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
directoriesClient := directories.New()
directoriesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := directoriesClient.Create(ctx, accountName, shareName, directoryName, metadata); err != nil {
return fmt.Errorf("Error creating Directory: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/file/directories/client.go 0000664 0000000 0000000 00000001132 14232154237 0023154 0 ustar 00root root 0000000 0000000 package directories
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/file/directories/create.go 0000664 0000000 0000000 00000007054 14232154237 0023152 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates a new directory under the specified share or parent directory.
func (client Client) Create(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Create", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Create", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/directories/delete.go 0000664 0000000 0000000 00000006343 14232154237 0023151 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete removes the specified empty directory
// Note that the directory must be empty before it can be deleted.
func (client Client) Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Delete", "`path` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/directories/get.go 0000664 0000000 0000000 00000007432 14232154237 0022466 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
// A set of name-value pairs that contain metadata for the directory.
MetaData map[string]string
// The value of this header is set to true if the directory metadata is completely
// encrypted using the specified algorithm. Otherwise, the value is set to false.
DirectoryMetaDataEncrypted bool
}
// Get returns all system properties for the specified directory,
// and can also be used to check the existence of a directory.
func (client Client) Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Get", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Get", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Get", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Get", "`path` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
result.DirectoryMetaDataEncrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/directories/lifecycle_test.go 0000664 0000000 0000000 00000007306 14232154237 0024705 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestDirectoriesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
directoriesClient := NewWithEnvironment(client.Environment)
directoriesClient.Client = client.PrepareWithAuthorizer(directoriesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, true)
metaData := map[string]string{
"hello": "world",
}
log.Printf("[DEBUG] Creating Top Level..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello", metaData); err != nil {
t.Fatalf("Error creating Top Level Directory: %s", err)
}
log.Printf("[DEBUG] Creating Inner..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello/there", metaData); err != nil {
t.Fatalf("Error creating Inner Directory: %s", err)
}
log.Printf("[DEBUG] Retrieving share")
innerDir, err := directoriesClient.Get(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving Inner Directory: %s", err)
}
if innerDir.DirectoryMetaDataEncrypted != true {
t.Fatalf("Expected MetaData to be encrypted but got: %t", innerDir.DirectoryMetaDataEncrypted)
}
if len(innerDir.MetaData) != 1 {
t.Fatalf("Expected MetaData to contain 1 item but got %d", len(innerDir.MetaData))
}
if innerDir.MetaData["hello"] != "world" {
t.Fatalf("Expected MetaData `hello` to be `world`: %s", innerDir.MetaData["hello"])
}
log.Printf("[DEBUG] Setting MetaData")
updatedMetaData := map[string]string{
"panda": "pops",
}
if _, err := directoriesClient.SetMetaData(ctx, accountName, shareName, "hello/there", updatedMetaData); err != nil {
t.Fatalf("Error updating MetaData: %s", err)
}
log.Printf("[DEBUG] Retrieving MetaData")
retrievedMetaData, err := directoriesClient.GetMetaData(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving the updated metadata: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected the updated metadata to have 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["panda"] != "pops" {
t.Fatalf("Expected the metadata `panda` to be `pops` but got %q", retrievedMetaData.MetaData["panda"])
}
t.Logf("[DEBUG] Deleting Inner..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello/there"); err != nil {
t.Fatalf("Error deleting Inner Directory: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello"); err != nil {
t.Fatalf("Error deleting Top Level Directory: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/file/directories/metadata_get.go 0000664 0000000 0000000 00000007127 14232154237 0024327 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns all user-defined metadata for the specified directory
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`path` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/directories/metadata_set.go 0000664 0000000 0000000 00000007273 14232154237 0024345 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates user defined metadata for the specified directory
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/directories/resource_id.go 0000664 0000000 0000000 00000003113 14232154237 0024202 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Directory
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, shareName, directoryName)
}
type ResourceID struct {
AccountName string
DirectoryName string
ShareName string
}
// ParseResourceID parses the Resource ID into an Object
// which can be used to interact with the Directory within the File Share
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar/Folder
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/file/directories/resource_id_test.go 0000664 0000000 0000000 00000004246 14232154237 0025251 0 ustar 00root root 0000000 0000000 package directories
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2017-07-29/file/directories/version.go 0000664 0000000 0000000 00000000471 14232154237 0023370 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/file/files/ 0000775 0000000 0000000 00000000000 14232154237 0020140 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/file/files/README.md 0000664 0000000 0000000 00000001743 14232154237 0021424 0 ustar 00root root 0000000 0000000 ## File Storage Files SDK for API version 2017-07-29
This package allows you to interact with the Files File Storage API
### Supported Authorizers
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/files"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
fileName := "example.txt"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
filesClient := files.New()
filesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := files.CreateInput{}
if _, err := filesClient.Create(ctx, accountName, shareName, directoryName, fileName, input); err != nil {
return fmt.Errorf("Error creating File: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/file/files/client.go 0000664 0000000 0000000 00000001124 14232154237 0021743 0 ustar 00root root 0000000 0000000 package files
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/file/files/copy.go 0000664 0000000 0000000 00000011216 14232154237 0021442 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the URL of the source file or blob, up to 2 KB in length.
//
// To copy a file to another file within the same storage account, you may use Shared Key to authenticate
// the source file. If you are copying a file from another storage account, or if you are copying a blob from
// the same storage account or another storage account, then you must authenticate the source file or blob using a
// shared access signature. If the source is a public blob, no authentication is required to perform the copy
// operation. A file in a share snapshot can also be specified as a copy source.
CopySource string
MetaData map[string]string
}
type CopyResult struct {
autorest.Response
// The CopyID, which can be passed to AbortCopy to abort the copy.
CopyID string
// Either `success` or `pending`
CopySuccess string
}
// Copy copies a blob or file to a destination file within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Copy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Copy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Copy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Copy", "`fileName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("files.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Copy", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CopyPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopySuccess = resp.Header.Get("x-ms-copy-status")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/copy_abort.go 0000664 0000000 0000000 00000007157 14232154237 0022642 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// AbortCopy aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata
func (client Client) AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`fileName` cannot be an empty string.")
}
if copyID == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`copyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, shareName, path, fileName, copyID)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, shareName, path, fileName, copyID string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", copyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/copy_wait.go 0000664 0000000 0000000 00000002414 14232154237 0022466 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
)
type CopyAndWaitResult struct {
autorest.Response
CopyID string
}
const DefaultCopyPollDuration = 15 * time.Second
// CopyAndWait is a convenience method which doesn't exist in the API, which copies the file and then waits for the copy to complete
func (client Client) CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error) {
copy, e := client.Copy(ctx, accountName, shareName, path, fileName, input)
if err != nil {
result.Response = copy.Response
err = fmt.Errorf("Error copying: %s", e)
return
}
result.CopyID = copy.CopyID
// since the API doesn't return a LRO, this is a hack which also polls every 10s, but should be sufficient
for true {
props, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if e != nil {
result.Response = copy.Response
err = fmt.Errorf("Error waiting for copy: %s", e)
return
}
switch strings.ToLower(props.CopyStatus) {
case "pending":
time.Sleep(pollDuration)
continue
case "success":
return
default:
err = fmt.Errorf("Unexpected CopyState %q", e)
return
}
}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/copy_wait_test.go 0000664 0000000 0000000 00000011043 14232154237 0023523 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestFilesCopyAndWaitFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
copiedFileName := "ubuntu.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
func TestFilesCopyAndWaitFromBlob(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
originalFileName := "ubuntu.iso"
copiedFileName := "ubuntu-copied.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting the original file..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", originalFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Now copying that blob..")
duplicateInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetFileEndpoint(filesClient.BaseURI, accountName), shareName, originalFileName),
}
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, duplicateInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copying duplicate: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
giovanni-0.20.0/storage/2017-07-29/file/files/create.go 0000664 0000000 0000000 00000011330 14232154237 0021730 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// This header specifies the maximum size for the file, up to 1 TiB.
ContentLength int64
// The MIME content type of the file
// If not specified, the default type is application/octet-stream.
ContentType *string
// Specifies which content encodings have been applied to the file.
// This value is returned to the client when the Get File operation is performed
// on the file resource and can be used to decode file content.
ContentEncoding *string
// Specifies the natural languages used by this resource.
ContentLanguage *string
// The File service stores this value but does not use or modify it.
CacheControl *string
// Sets the file's MD5 hash.
ContentMD5 *string
// Sets the file’s Content-Disposition header.
ContentDisposition *string
MetaData map[string]string
}
// Create creates a new file or replaces a file.
func (client Client) Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Create", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Create", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Create", "`input.MetaData` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-content-length": input.ContentLength,
"x-ms-type": "file",
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/delete.go 0000664 0000000 0000000 00000006206 14232154237 0021735 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete immediately deletes the file from the File Share.
func (client Client) Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Delete", "`fileName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/lifecycle_test.go 0000664 0000000 0000000 00000011627 14232154237 0023474 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestFilesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
fileName := "bled5.png"
contentEncoding := "application/vnd+panda"
t.Logf("[DEBUG] Creating Top Level File..")
createInput := CreateInput{
ContentLength: 1024,
ContentEncoding: &contentEncoding,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Top-Level File..")
file, err := filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 1024 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != contentEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", contentEncoding, file.ContentEncoding)
}
updatedSize := int64(2048)
updatedEncoding := "application/vnd+pandas2"
updatedInput := SetPropertiesInput{
ContentEncoding: &updatedEncoding,
ContentLength: &updatedSize,
}
if _, err := filesClient.SetProperties(ctx, accountName, shareName, "", fileName, updatedInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Properties for the Top-Level File..")
file, err = filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 2048 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != updatedEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", updatedEncoding, file.ContentEncoding)
}
t.Logf("[DEBUG] Setting MetaData..")
metaData := map[string]string{
"hello": "there",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Retrieving MetaData..")
retrievedMetaData, err := filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
t.Logf("[DEBUG] Re-Setting MetaData..")
metaData = map[string]string{
"hello": "there",
"second": "thing",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving MetaData..")
retrievedMetaData, err = filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 2 {
t.Fatalf("Expected 2 items but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
if retrievedMetaData.MetaData["second"] != "thing" {
t.Fatalf("Expected `second` to be `thing` but got %q", retrievedMetaData.MetaData["second"])
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/file/files/metadata_get.go 0000664 0000000 0000000 00000007263 14232154237 0023116 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData for the specified File.
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`fileName` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
//metadata.ByParsingFromHeaders(&result.MetaData),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/metadata_set.go 0000664 0000000 0000000 00000007347 14232154237 0023135 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates the specified File to have the specified MetaData.
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("files.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, fileName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/properties_get.go 0000664 0000000 0000000 00000012146 14232154237 0023526 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
CacheControl string
ContentDisposition string
ContentEncoding string
ContentLanguage string
ContentLength *int64
ContentMD5 string
ContentType string
CopyID string
CopyStatus string
CopySource string
CopyProgress string
CopyStatusDescription string
CopyCompletionTime string
Encrypted bool
MetaData map[string]string
}
// GetProperties returns the Properties for the specified file
func (client Client) GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("x-ms-content-md5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = resp.Header.Get("x-ms-copy-status")
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.Encrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
contentLengthRaw := resp.Header.Get("Content-Length")
if contentLengthRaw != "" {
contentLength, err := strconv.Atoi(contentLengthRaw)
if err != nil {
return result, fmt.Errorf("Error parsing %q for Content-Length as an integer: %s", contentLengthRaw, err)
}
contentLengthI64 := int64(contentLength)
result.ContentLength = &contentLengthI64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/properties_set.go 0000664 0000000 0000000 00000013714 14232154237 0023544 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
// Resizes a file to the specified size.
// If the specified byte value is less than the current size of the file,
// then all ranges above the specified byte value are cleared.
ContentLength *int64
// Modifies the cache control string for the file.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentControl *string
// Sets the file’s Content-Disposition header.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentDisposition *string
// Sets the file's content encoding.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentEncoding *string
// Sets the file's content language.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentLanguage *string
// Sets the file's MD5 hash.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentMD5 *string
// Sets the file's content type.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentType *string
}
// SetProperties sets the specified properties on the specified File
func (client Client) SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-type": "file",
}
if input.ContentControl != nil {
headers["x-ms-cache-control"] = *input.ContentControl
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-content-language"] = *input.ContentLanguage
}
if input.ContentLength != nil {
headers["x-ms-content-length"] = *input.ContentLength
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/range_clear.go 0000664 0000000 0000000 00000007740 14232154237 0022741 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ClearByteRangeInput struct {
StartBytes int64
EndBytes int64
}
// ClearByteRange clears the specified Byte Range from within the specified File
func (client Client) ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.EndBytes` must be greater than 0.")
}
req, err := client.ClearByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", nil, "Failure preparing request")
return
}
resp, err := client.ClearByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure sending request")
return
}
result, err = client.ClearByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure responding to request")
return
}
return
}
// ClearByteRangePreparer prepares the ClearByteRange request.
func (client Client) ClearByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes),
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ClearByteRangeSender sends the ClearByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ClearByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ClearByteRangeResponder handles the response to the ClearByteRange request. The method always
// closes the http.Response Body.
func (client Client) ClearByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/range_get.go 0000664 0000000 0000000 00000010430 14232154237 0022420 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetByteRangeInput struct {
StartBytes int64
EndBytes int64
}
type GetByteRangeResult struct {
autorest.Response
Contents []byte
}
// GetByteRange returns the specified Byte Range from the specified File.
func (client Client) GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at most 4MB.")
}
req, err := client.GetByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", nil, "Failure preparing request")
return
}
resp, err := client.GetByteRangeSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure sending request")
return
}
result, err = client.GetByteRangeResponder(resp, expectedBytes)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure responding to request")
return
}
return
}
// GetByteRangePreparer prepares the GetByteRange request.
func (client Client) GetByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetByteRangeSender sends the GetByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetByteRangeResponder handles the response to the GetByteRange request. The method always
// closes the http.Response Body.
func (client Client) GetByteRangeResponder(resp *http.Response, length int64) (result GetByteRangeResult, err error) {
result.Contents = make([]byte, length)
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/range_get_file.go 0000664 0000000 0000000 00000006055 14232154237 0023427 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"log"
"math"
"runtime"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// GetFile is a helper method to download a file by chunking it automatically
func (client Client) GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error) {
// first look up the file and check out how many bytes it is
file, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if err != nil {
result = file.Response
err = e
return
}
if file.ContentLength == nil {
err = fmt.Errorf("Content-Length was nil!")
return
}
length := int64(*file.ContentLength)
chunkSize := int64(4 * 1024 * 1024) // 4MB
if chunkSize > length {
chunkSize = length
}
// then split that up into chunks and retrieve it retrieve it into the 'results' set
chunks := int(math.Ceil(float64(length) / float64(chunkSize)))
workerCount := parallelism * runtime.NumCPU()
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
results := make([]*downloadFileChunkResult, chunks)
errors := make(chan error, chunkSize)
for i := 0; i < chunks; i++ {
go func(i int) {
log.Printf("[DEBUG] Downloading Chunk %d of %d", i+1, chunks)
dfci := downloadFileChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: length,
}
result, err := client.downloadFileChunk(ctx, accountName, shareName, path, fileName, dfci)
if err != nil {
errors <- err
waitGroup.Done()
return
}
// if there's no error, we should have bytes, so this is safe
results[i] = result
waitGroup.Done()
}(i)
}
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
err = fmt.Errorf("Error downloading file: %s", <-errors)
return
}
// then finally put it all together, in order and return it
output := make([]byte, length)
for _, v := range results {
copy(output[v.startBytes:v.endBytes], v.bytes)
}
outputBytes = output
return
}
type downloadFileChunkInput struct {
thisChunk int
chunkSize int64
fileSize int64
}
type downloadFileChunkResult struct {
startBytes int64
endBytes int64
bytes []byte
}
func (client Client) downloadFileChunk(ctx context.Context, accountName, shareName, path, fileName string, input downloadFileChunkInput) (*downloadFileChunkResult, error) {
startBytes := input.chunkSize * int64(input.thisChunk)
endBytes := startBytes + input.chunkSize
// the last chunk may exceed the size of the file
remaining := input.fileSize - startBytes
if input.chunkSize > remaining {
endBytes = startBytes + remaining
}
getInput := GetByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
}
result, err := client.GetByteRange(ctx, accountName, shareName, path, fileName, getInput)
if err != nil {
return nil, fmt.Errorf("Error putting bytes: %s", err)
}
output := downloadFileChunkResult{
startBytes: startBytes,
endBytes: endBytes,
bytes: result.Contents,
}
return &output, nil
}
giovanni-0.20.0/storage/2017-07-29/file/files/range_get_file_test.go 0000664 0000000 0000000 00000007063 14232154237 0024466 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestGetSmallFile(t *testing.T) {
// the purpose of this test is to verify that the small, single-chunked file gets downloaded correctly
testGetFile(t, "small-file.png", "image/png")
}
func TestGetLargeFile(t *testing.T) {
// the purpose of this test is to verify that the large, multi-chunked file gets downloaded correctly
testGetFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testGetFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Downloading file..")
_, downloadedBytes, err := filesClient.GetFile(ctx, accountName, shareName, "", fileName, 4)
if err != nil {
t.Fatalf("Error downloading file: %s", err)
}
t.Logf("[DEBUG] Asserting the files are the same size..")
expectedBytes := make([]byte, info.Size())
file.Read(expectedBytes)
if len(expectedBytes) != len(downloadedBytes) {
t.Fatalf("Expected %d bytes but got %d", len(expectedBytes), len(downloadedBytes))
}
t.Logf("[DEBUG] Asserting the files are the same content-wise..")
// overkill, but it's this or shasum-ing
for i := int64(0); i < info.Size(); i++ {
if expectedBytes[i] != downloadedBytes[i] {
t.Fatalf("Expected byte %d to be %q but got %q", i, expectedBytes[i], downloadedBytes[i])
}
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/file/files/range_put.go 0000664 0000000 0000000 00000011226 14232154237 0022455 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutByteRangeInput struct {
StartBytes int64
EndBytes int64
// Content is the File Contents for the specified range
// which can be at most 4MB
Content []byte
}
// PutByteRange puts the specified Byte Range in the specified File.
func (client Client) PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
actualBytes := len(input.Content)
if expectedBytes != int64(actualBytes) {
return result, validation.NewError("files.Client", "PutByteRange", fmt.Sprintf("The specified byte-range (%d) didn't match the content size (%d).", expectedBytes, actualBytes))
}
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at most 4MB.")
}
req, err := client.PutByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", nil, "Failure preparing request")
return
}
resp, err := client.PutByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure sending request")
return
}
result, err = client.PutByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure responding to request")
return
}
return
}
// PutByteRangePreparer prepares the PutByteRange request.
func (client Client) PutByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
"Content-Length": int(len(input.Content)),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutByteRangeSender sends the PutByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutByteRangeResponder handles the response to the PutByteRange request. The method always
// closes the http.Response Body.
func (client Client) PutByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/range_put_file.go 0000664 0000000 0000000 00000005070 14232154237 0023454 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"io"
"log"
"math"
"os"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// PutFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
chunkSize := 4 * 1024 * 1024 // 4MB
if chunkSize > int(fileSize) {
chunkSize = int(fileSize)
}
chunks := int(math.Ceil(float64(fileSize) / float64(chunkSize*1.0)))
workerCount := parallelism
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
jobs := make(chan int, workerCount)
errors := make(chan error, chunkSize)
for i := 0; i < workerCount; i++ {
go func() {
for i := range jobs {
log.Printf("[DEBUG] Chunk %d of %d", i+1, chunks)
uci := uploadChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: fileSize,
}
_, err := client.uploadChunk(ctx, accountName, shareName, path, fileName, uci, file)
if err != nil {
errors <- err
}
}
waitGroup.Done()
}()
}
for i := 0; i < chunks; i++ {
jobs <- i
}
close(jobs)
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
return fmt.Errorf("Error uploading file: %s", <-errors)
}
return nil
}
type uploadChunkInput struct {
thisChunk int
chunkSize int
fileSize int64
}
func (client Client) uploadChunk(ctx context.Context, accountName, shareName, path, fileName string, input uploadChunkInput, file *os.File) (result autorest.Response, err error) {
startBytes := int64(input.chunkSize * input.thisChunk)
endBytes := startBytes + int64(input.chunkSize)
// the last size may exceed the size of the file
remaining := input.fileSize - startBytes
if int64(input.chunkSize) > remaining {
endBytes = startBytes + remaining
}
bytesToRead := int(endBytes) - int(startBytes)
bytes := make([]byte, bytesToRead)
_, err = file.ReadAt(bytes, startBytes)
if err != nil {
if err != io.EOF {
return result, fmt.Errorf("Error reading bytes: %s", err)
}
}
putBytesInput := PutByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
Content: bytes,
}
result, err = client.PutByteRange(ctx, accountName, shareName, path, fileName, putBytesInput)
if err != nil {
return result, fmt.Errorf("Error putting bytes: %s", err)
}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/range_put_file_test.go 0000664 0000000 0000000 00000005413 14232154237 0024514 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPutSmallFile(t *testing.T) {
// the purpose of this test is to ensure that a small file (< 4MB) is a single chunk
testPutFile(t, "small-file.png", "image/png")
}
func TestPutLargeFile(t *testing.T) {
// the purpose of this test is to ensure that large files (> 4MB) are chunked
testPutFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testPutFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/file/files/ranges_list.go 0000664 0000000 0000000 00000007277 14232154237 0023016 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListRangesResult struct {
autorest.Response
Ranges []Range `xml:"Range"`
}
type Range struct {
Start string `xml:"Start"`
End string `xml:"End"`
}
// ListRanges returns the list of valid ranges for the specified File.
func (client Client) ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("files.Client", "ListRanges", "`path` cannot be an empty string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`fileName` cannot be an empty string.")
}
req, err := client.ListRangesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", nil, "Failure preparing request")
return
}
resp, err := client.ListRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure sending request")
return
}
result, err = client.ListRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure responding to request")
return
}
return
}
// ListRangesPreparer prepares the ListRanges request.
func (client Client) ListRangesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "rangelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListRangesSender sends the ListRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListRangesResponder handles the response to the ListRanges request. The method always
// closes the http.Response Body.
func (client Client) ListRangesResponder(resp *http.Response) (result ListRangesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/files/resource_id.go 0000664 0000000 0000000 00000003654 14232154237 0023002 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName, filePath string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s/%s", domain, shareName, directoryName, filePath)
}
type ResourceID struct {
AccountName string
DirectoryName string
FileName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with Files within a Storage Share.
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
fileName := segments[len(segments)-1]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
directoryName = strings.TrimSuffix(directoryName, fileName)
directoryName = strings.TrimSuffix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
FileName: fileName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/file/files/resource_id_test.go 0000664 0000000 0000000 00000007430 14232154237 0024035 0 ustar 00root root 0000000 0000000 package files
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1", "file1.txt")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/directory2/file1.txt",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1/directory2" {
t.Fatalf("Expected Directory Name to be `directory1/directory2` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
}
giovanni-0.20.0/storage/2017-07-29/file/files/version.go 0000664 0000000 0000000 00000000463 14232154237 0022157 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/file/shares/ 0000775 0000000 0000000 00000000000 14232154237 0020323 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/file/shares/README.md 0000664 0000000 0000000 00000001656 14232154237 0021612 0 ustar 00root root 0000000 0000000 ## File Storage Shares SDK for API version 2017-07-29
This package allows you to interact with the Shares File Storage API
### Supported Authorizers
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/file/shares"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
sharesClient := shares.New()
sharesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := shares.CreateInput{
QuotaInGB: 2,
}
if _, err := sharesClient.Create(ctx, accountName, shareName, input); err != nil {
return fmt.Errorf("Error creating Share: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/file/shares/acl_get.go 0000664 0000000 0000000 00000006213 14232154237 0022252 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL get the Access Control List for the specified Storage Share
func (client Client) GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.GetACLPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/acl_set.go 0000664 0000000 0000000 00000006415 14232154237 0022272 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"encoding/xml"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List on the specified Storage Share
func (client Client) SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.SetACLPreparer(ctx, accountName, shareName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/client.go 0000664 0000000 0000000 00000001125 14232154237 0022127 0 ustar 00root root 0000000 0000000 package shares
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/file/shares/create.go 0000664 0000000 0000000 00000007365 14232154237 0022130 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies the maximum size of the share, in gigabytes.
// Must be greater than 0, and less than or equal to 5TB (5120).
QuotaInGB int
MetaData map[string]string
}
// Create creates the specified Storage Share within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Create", "`shareName` must be a lower-cased string.")
}
if input.QuotaInGB <= 0 || input.QuotaInGB > 102400 {
return result, validation.NewError("shares.Client", "Create", "`input.QuotaInGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": input.QuotaInGB,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/delete.go 0000664 0000000 0000000 00000006120 14232154237 0022113 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Storage Share from within a Storage Account
func (client Client) Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Delete", "`shareName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, deleteSnapshots)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if deleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/lifecycle_test.go 0000664 0000000 0000000 00000020771 14232154237 0023657 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestSharesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 5)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 5 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
func TestSharesLifecycleLargeQuota(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResourcesWithSku(ctx, resourceGroup, accountName, storage.KindFileStorage, storage.SkuNamePremiumLRS)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1001,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1001 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 6000)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 6000 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/file/shares/metadata_get.go 0000664 0000000 0000000 00000006525 14232154237 0023301 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData associated with the specified Storage Share
func (client Client) GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/metadata_set.go 0000664 0000000 0000000 00000006703 14232154237 0023313 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the MetaData on the specified Storage Share
func (client Client) SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("shares.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/models.go 0000664 0000000 0000000 00000000416 14232154237 0022136 0 ustar 00root root 0000000 0000000 package shares
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2017-07-29/file/shares/properties_get.go 0000664 0000000 0000000 00000007150 14232154237 0023710 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesResult struct {
autorest.Response
MetaData map[string]string
ShareQuota int
}
// GetProperties returns the properties about the specified Storage Share
func (client Client) GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
quotaRaw := resp.Header.Get("x-ms-share-quota")
if quotaRaw != "" {
quota, e := strconv.Atoi(quotaRaw)
if e != nil {
return result, fmt.Errorf("Error converting %q to an integer: %s", quotaRaw, err)
}
result.ShareQuota = quota
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/properties_set.go 0000664 0000000 0000000 00000006617 14232154237 0023733 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetProperties lets you update the Quota for the specified Storage Share
func (client Client) SetProperties(ctx context.Context, accountName, shareName string, newQuotaGB int) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if newQuotaGB <= 0 || newQuotaGB > 102400 {
return result, validation.NewError("shares.Client", "SetProperties", "`newQuotaGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, newQuotaGB)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName string, quotaGB int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": quotaGB,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/resource_id.go 0000664 0000000 0000000 00000002320 14232154237 0023152 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File Share
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
type ResourceID struct {
AccountName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Storage Shares SDK
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
shareName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/file/shares/resource_id_test.go 0000664 0000000 0000000 00000003671 14232154237 0024223 0 ustar 00root root 0000000 0000000 package shares
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected the share name to be `share1` but got %q", actual.ShareName)
}
}
}
giovanni-0.20.0/storage/2017-07-29/file/shares/snapshot_create.go 0000664 0000000 0000000 00000010266 14232154237 0024041 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateSnapshotInput struct {
MetaData map[string]string
}
type CreateSnapshotResult struct {
autorest.Response
// This header is a DateTime value that uniquely identifies the share snapshot.
// The value of this header may be used in subsequent requests to access the share snapshot.
// This value is opaque.
SnapshotDateTime string
}
// CreateSnapshot creates a read-only snapshot of the share
// A share can support creation of 200 share snapshots. Attempting to create more than 200 share snapshots fails with 409 (Conflict).
// Attempting to create a share snapshot while a previous Snapshot Share operation is in progress fails with 409 (Conflict).
func (client Client) CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "CreateSnapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreateSnapshotPreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.CreateSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure sending request")
return
}
result, err = client.CreateSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure responding to request")
return
}
return
}
// CreateSnapshotPreparer prepares the CreateSnapshot request.
func (client Client) CreateSnapshotPreparer(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSnapshotSender sends the CreateSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateSnapshotResponder handles the response to the CreateSnapshot request. The method always
// closes the http.Response Body.
func (client Client) CreateSnapshotResponder(resp *http.Response) (result CreateSnapshotResult, err error) {
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/snapshot_delete.go 0000664 0000000 0000000 00000006552 14232154237 0024043 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// DeleteSnapshot deletes the specified Snapshot of a Storage Share
func (client Client) DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` must be a lower-cased string.")
}
if shareSnapshot == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareSnapshot` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, shareName, shareSnapshot)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, shareName string, shareSnapshot string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
"sharesnapshot": autorest.Encode("query", shareSnapshot),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/snapshot_get.go 0000664 0000000 0000000 00000007101 14232154237 0023347 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetSnapshotPropertiesResult struct {
autorest.Response
MetaData map[string]string
}
// GetSnapshot gets information about the specified Snapshot of the specified Storage Share
func (client Client) GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` must be a lower-cased string.")
}
if snapshotShare == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`snapshotShare` cannot be an empty string.")
}
req, err := client.GetSnapshotPreparer(ctx, accountName, shareName, snapshotShare)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.GetSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure sending request")
return
}
result, err = client.GetSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPreparer(ctx context.Context, accountName, shareName, snapshotShare string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"snapshot": autorest.Encode("query", snapshotShare),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSnapshotSender sends the GetSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetSnapshotResponder handles the response to the GetSnapshot request. The method always
// closes the http.Response Body.
func (client Client) GetSnapshotResponder(resp *http.Response) (result GetSnapshotPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/stats.go 0000664 0000000 0000000 00000006470 14232154237 0022017 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetStatsResult struct {
autorest.Response
// The approximate size of the data stored on the share.
// Note that this value may not include all recently created or recently resized files.
ShareUsageBytes int64 `xml:"ShareUsageBytes"`
}
// GetStats returns information about the specified Storage Share
func (client Client) GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` must be a lower-cased string.")
}
req, err := client.GetStatsPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", nil, "Failure preparing request")
return
}
resp, err := client.GetStatsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure sending request")
return
}
result, err = client.GetStatsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure responding to request")
return
}
return
}
// GetStatsPreparer prepares the GetStats request.
func (client Client) GetStatsPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "stats"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetStatsSender sends the GetStats request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetStatsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetStatsResponder handles the response to the GetStats request. The method always
// closes the http.Response Body.
func (client Client) GetStatsResponder(resp *http.Response) (result GetStatsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/file/shares/version.go 0000664 0000000 0000000 00000000464 14232154237 0022343 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/queue/ 0000775 0000000 0000000 00000000000 14232154237 0017243 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/queue/messages/ 0000775 0000000 0000000 00000000000 14232154237 0021052 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/queue/messages/README.md 0000664 0000000 0000000 00000001741 14232154237 0022334 0 ustar 00root root 0000000 0000000 ## Queue Storage Messages SDK for API version 2017-07-29
This package allows you to interact with the Messages Queue Storage API
### Supported Authorizers
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/queue/messages"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
messagesClient := messages.New()
messagesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := messages.PutInput{
Message: "hello",
}
if _, err := messagesClient.Put(ctx, accountName, queueName, input); err != nil {
return fmt.Errorf("Error creating Message: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/queue/messages/client.go 0000664 0000000 0000000 00000001114 14232154237 0022654 0 ustar 00root root 0000000 0000000 package messages
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Messages.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/delete.go 0000664 0000000 0000000 00000006523 14232154237 0022651 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a specific message
func (client Client) Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Delete", "`queueName` must be a lower-cased string.")
}
if messageID == "" {
return result, validation.NewError("messages.Client", "Delete", "`messageID` cannot be an empty string.")
}
if popReceipt == "" {
return result, validation.NewError("messages.Client", "Delete", "`popReceipt` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName, messageID, popReceipt)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, queueName, messageID, popReceipt string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", popReceipt),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/get.go 0000664 0000000 0000000 00000007666 14232154237 0022177 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
// VisibilityTimeout specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
VisibilityTimeout *int
}
// Get retrieves one or more messages from the front of the queue
func (client Client) Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Get", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Get", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Get", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Get", "`numberOfMessages` must be between 1 and 32.")
}
if input.VisibilityTimeout != nil {
t := *input.VisibilityTimeout
maxTime := (time.Hour * 24 * 7).Seconds()
if t < 1 || t < int(maxTime) {
return result, validation.NewError("messages.Client", "Get", "`input.VisibilityTimeout` must be larger than or equal to 1 second, and cannot be larger than 7 days.")
}
}
req, err := client.GetPreparer(ctx, accountName, queueName, numberOfMessages, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("query", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/lifecycle_test.go 0000664 0000000 0000000 00000005514 14232154237 0024404 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/queue/queues"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
queuesClient := queues.NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithAuthorizer(queuesClient.Client, storageAuth)
messagesClient := NewWithEnvironment(client.Environment)
messagesClient.Client = client.PrepareWithAuthorizer(messagesClient.Client, storageAuth)
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error creating queue: %s", err)
}
defer queuesClient.Delete(ctx, accountName, queueName)
input := PutInput{
Message: "ohhai",
}
putResp, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message in queue: %s", err)
}
messageId := (*putResp.QueueMessages)[0].MessageId
popReceipt := (*putResp.QueueMessages)[0].PopReceipt
_, err = messagesClient.Update(ctx, accountName, queueName, messageId, UpdateInput{
PopReceipt: popReceipt,
Message: "Updated message",
VisibilityTimeout: 65,
})
if err != nil {
t.Fatalf("Error updating: %s", err)
}
for i := 0; i < 5; i++ {
input := PutInput{
Message: fmt.Sprintf("Message %d", i),
}
_, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message %d in queue: %s", i, err)
}
}
peakedMessages, err := messagesClient.Peek(ctx, accountName, queueName, 3)
if err != nil {
t.Fatalf("Error peaking messages: %s", err)
}
for _, v := range *peakedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
}
retrievedMessages, err := messagesClient.Get(ctx, accountName, queueName, 6, GetInput{})
if err != nil {
t.Fatalf("Error retrieving messages: %s", err)
}
for _, v := range *retrievedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
_, err = messagesClient.Delete(ctx, accountName, queueName, v.MessageId, v.PopReceipt)
if err != nil {
t.Fatalf("Error deleting message from queue: %s", err)
}
}
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/models.go 0000664 0000000 0000000 00000001010 14232154237 0022654 0 ustar 00root root 0000000 0000000 package messages
import "github.com/Azure/go-autorest/autorest"
type QueueMessage struct {
MessageText string `xml:"MessageText"`
}
type QueueMessagesListResult struct {
autorest.Response
QueueMessages *[]QueueMessageResponse `xml:"QueueMessage"`
}
type QueueMessageResponse struct {
MessageId string `xml:"MessageId"`
InsertionTime string `xml:"InsertionTime"`
ExpirationTime string `xml:"ExpirationTime"`
PopReceipt string `xml:"PopReceipt"`
TimeNextVisible string `xml:"TimeNextVisible"`
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/peek.go 0000664 0000000 0000000 00000006512 14232154237 0022331 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Peek retrieves one or more messages from the front of the queue, but doesn't alter the visibility of the messages
func (client Client) Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Peek", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Peek", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Peek", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Peek", "`numberOfMessages` must be between 1 and 32.")
}
req, err := client.PeekPreparer(ctx, accountName, queueName, numberOfMessages)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", nil, "Failure preparing request")
return
}
resp, err := client.PeekSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure sending request")
return
}
result, err = client.PeekResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure responding to request")
return
}
return
}
// PeekPreparer prepares the Peek request.
func (client Client) PeekPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
"peekonly": autorest.Encode("query", true),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PeekSender sends the Peek request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PeekSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PeekResponder handles the response to the Peek request. The method always
// closes the http.Response Body.
func (client Client) PeekResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/put.go 0000664 0000000 0000000 00000010107 14232154237 0022210 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// The maximum time-to-live can be any positive number,
// as well as -1 indicating that the message does not expire.
// If this parameter is omitted, the default time-to-live is 7 days.
MessageTtl *int
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// visibilitytimeout should be set to a value smaller than the time-to-live value.
// If not specified, the default value is 0.
VisibilityTimeout *int
}
// Put adds a new message to the back of the message queue
func (client Client) Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Put", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Put", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Put", "`queueName` must be a lower-cased string.")
}
req, err := client.PutPreparer(ctx, accountName, queueName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", nil, "Failure preparing request")
return
}
resp, err := client.PutSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure sending request")
return
}
result, err = client.PutResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure responding to request")
return
}
return
}
// PutPreparer prepares the Put request.
func (client Client) PutPreparer(ctx context.Context, accountName, queueName string, input PutInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{}
if input.MessageTtl != nil {
queryParameters["messagettl"] = autorest.Encode("path", *input.MessageTtl)
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("path", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutSender sends the Put request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutResponder handles the response to the Put request. The method always
// closes the http.Response Body.
func (client Client) PutResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/resource_id.go 0000664 0000000 0000000 00000003044 14232154237 0023705 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Message within a Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName, messageID string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/messages/%s", domain, queueName, messageID)
}
type ResourceID struct {
AccountName string
QueueName string
MessageID string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Message within a Queue
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) != 3 {
return nil, fmt.Errorf("Expected the path to contain 3 segments but got %d", len(segments))
}
queueName := segments[0]
messageID := segments[2]
return &ResourceID{
AccountName: *accountName,
MessageID: messageID,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/resource_id_test.go 0000664 0000000 0000000 00000004321 14232154237 0024743 0 ustar 00root root 0000000 0000000 package messages
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1", "message1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected Queue Name to be `queue1` but got %q", actual.QueueName)
}
if actual.MessageID != "message1" {
t.Fatalf("Expected Message ID to be `message1` but got %q", actual.MessageID)
}
}
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/update.go 0000664 0000000 0000000 00000010071 14232154237 0022662 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type UpdateInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// Specifies the valid pop receipt value required to modify this message.
PopReceipt string
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// A message can be updated until it has been deleted or has expired.
VisibilityTimeout int
}
// Update updates an existing message based on it's Pop Receipt
func (client Client) Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Update", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Update", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Update", "`queueName` must be a lower-cased string.")
}
if input.PopReceipt == "" {
return result, validation.NewError("messages.Client", "Update", "`input.PopReceipt` cannot be an empty string.")
}
req, err := client.UpdatePreparer(ctx, accountName, queueName, messageID, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", nil, "Failure preparing request")
return
}
resp, err := client.UpdateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure sending request")
return
}
result, err = client.UpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure responding to request")
return
}
return
}
// UpdatePreparer prepares the Update request.
func (client Client) UpdatePreparer(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", input.PopReceipt),
"visibilitytimeout": autorest.Encode("query", input.VisibilityTimeout),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UpdateSender sends the Update request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UpdateResponder handles the response to the Update request. The method always
// closes the http.Response Body.
func (client Client) UpdateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/messages/version.go 0000664 0000000 0000000 00000000466 14232154237 0023074 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/ 0000775 0000000 0000000 00000000000 14232154237 0020552 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/queue/queues/README.md 0000664 0000000 0000000 00000001672 14232154237 0022037 0 ustar 00root root 0000000 0000000 ## Queue Storage Queues SDK for API version 2017-07-29
This package allows you to interact with the Queues Queue Storage API
### Supported Authorizers
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/queue/queues"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
queuesClient := queues.New()
queuesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := queuesClient.Create(ctx, accountName, queueName, metadata); err != nil {
return fmt.Errorf("Error creating Queue: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/queue/queues/client.go 0000664 0000000 0000000 00000001126 14232154237 0022357 0 ustar 00root root 0000000 0000000 package queues
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Queue Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/create.go 0000664 0000000 0000000 00000006247 14232154237 0022355 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates the specified Queue within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Create", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Create", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Create", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/delete.go 0000664 0000000 0000000 00000005502 14232154237 0022345 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Queue within the specified Storage Account
func (client Client) Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Delete", "`queueName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/lifecycle_test.go 0000664 0000000 0000000 00000005430 14232154237 0024101 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestQueuesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
queuesClient := NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithAuthorizer(queuesClient.Client, storageAuth)
// first let's test an empty container
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
// then let's retrieve it to ensure there's no metadata..
resp, err := queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// then let's add some..
updatedMetaData := map[string]string{
"band": "panic",
"boots": "the-overpass",
}
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, updatedMetaData)
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error re-retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 2 {
t.Fatalf("Expected metadata to have 2 items but got: %s", resp.MetaData)
}
if resp.MetaData["band"] != "panic" {
t.Fatalf("Expected `band` to be `panic` but got: %s", resp.MetaData["band"])
}
if resp.MetaData["boots"] != "the-overpass" {
t.Fatalf("Expected `boots` to be `the-overpass` but got: %s", resp.MetaData["boots"])
}
// and woo let's remove it again
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
log.Printf("[DEBUG] Deleting..")
_, err = queuesClient.Delete(ctx, accountName, queueName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/metadata_get.go 0000664 0000000 0000000 00000006376 14232154237 0023534 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the metadata for this Queue
func (client Client) GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/metadata_set.go 0000664 0000000 0000000 00000006576 14232154237 0023552 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData returns the metadata for this Queue
func (client Client) SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/models.go 0000664 0000000 0000000 00000002406 14232154237 0022366 0 ustar 00root root 0000000 0000000 package queues
type StorageServiceProperties struct {
Logging *LoggingConfig `xml:"Logging,omitempty"`
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
Cors *Cors `xml:"Cors,omitempty"`
}
type LoggingConfig struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
}
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
// Element IncludeAPIs is only expected when Metrics is enabled
IncludeAPIs *bool `xml:"IncludeAPIs,omitempty"`
}
type RetentionPolicy struct {
Enabled bool `xml:"Enabled"`
Days int `xml:"Days,omitempty"`
}
type Cors struct {
CorsRule CorsRule `xml:"CorsRule"`
}
type CorsRule struct {
AllowedOrigins string `xml:"AllowedOrigins"`
AllowedMethods string `xml:"AllowedMethods"`
AllowedHeaders string `xml:"AllowedHeaders`
ExposedHeaders string `xml:"ExposedHeaders"`
MaxAgeInSeconds int `xml:"MaxAgeInSeconds"`
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/resource_id.go 0000664 0000000 0000000 00000002315 14232154237 0023405 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, queueName)
}
type ResourceID struct {
AccountName string
QueueName string
}
// ParseResourceID parses the Resource ID and returns an Object which
// can be used to interact with a Queue within a Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.queue.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
queueName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/resource_id_test.go 0000664 0000000 0000000 00000003701 14232154237 0024444 0 ustar 00root root 0000000 0000000 package queues
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected the queue name to be `queue1` but got %q", actual.QueueName)
}
}
}
giovanni-0.20.0/storage/2017-07-29/queue/queues/version.go 0000664 0000000 0000000 00000000464 14232154237 0022572 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/table/ 0000775 0000000 0000000 00000000000 14232154237 0017206 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/table/entities/ 0000775 0000000 0000000 00000000000 14232154237 0021032 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/table/entities/README.md 0000664 0000000 0000000 00000002166 14232154237 0022316 0 ustar 00root root 0000000 0000000 ## Table Storage Entities SDK for API version 2017-07-29
This package allows you to interact with the Entities Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/table/entities"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
entitiesClient := entities.New()
entitiesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := entities.InsertEntityInput{
PartitionKey: "abc",
RowKey: "123",
MetaDataLevel: entities.NoMetaData,
Entity: map[string]interface{}{
"title": "Don't Kill My Vibe",
"artist": "Sigrid",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, input); err != nil {
return fmt.Errorf("Error creating Entity: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/table/entities/client.go 0000664 0000000 0000000 00000001130 14232154237 0022632 0 ustar 00root root 0000000 0000000 package entities
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/table/entities/delete.go 0000664 0000000 0000000 00000007327 14232154237 0022634 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteEntityInput struct {
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Delete deletes an existing entity in a table.
func (client Client) Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Delete", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.RowKey` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
// TODO: support for eTags
"If-Match": "*",
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/entities/get.go 0000664 0000000 0000000 00000007013 14232154237 0022141 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetEntityInput struct {
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
}
type GetEntityResult struct {
autorest.Response
Entity map[string]interface{}
}
// Get queries entities in a table and includes the $filter and $select options.
func (client Client) Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Get", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Get", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.RowKey` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, tableName string, input GetEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetEntityResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result.Entity),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/entities/insert.go 0000664 0000000 0000000 00000010207 14232154237 0022665 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertEntityInput struct {
// The level of MetaData provided for this Entity
MetaDataLevel MetaDataLevel
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Insert inserts a new entity into a table.
func (client Client) Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Insert", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Insert", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", nil, "Failure preparing request")
return
}
resp, err := client.InsertSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure sending request")
return
}
result, err = client.InsertResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure responding to request")
return
}
return
}
// InsertPreparer prepares the Insert request.
func (client Client) InsertPreparer(ctx context.Context, accountName, tableName string, input InsertEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"Prefer": "return-no-content",
}
input.Entity["PartitionKey"] = input.PartitionKey
input.Entity["RowKey"] = input.RowKey
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertSender sends the Insert request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertResponder handles the response to the Insert request. The method always
// closes the http.Response Body.
func (client Client) InsertResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/entities/insert_or_merge.go 0000664 0000000 0000000 00000010625 14232154237 0024550 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrMergeEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrMerge updates an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrMergePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrMergeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure sending request")
return
}
result, err = client.InsertOrMergeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure responding to request")
return
}
return
}
// InsertOrMergePreparer prepares the InsertOrMerge request.
func (client Client) InsertOrMergePreparer(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrMergeSender sends the InsertOrMerge request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrMergeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrMergeResponder handles the response to the InsertOrMerge request. The method always
// closes the http.Response Body.
func (client Client) InsertOrMergeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/entities/insert_or_replace.go 0000664 0000000 0000000 00000010706 14232154237 0025064 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrReplaceEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrReplace replaces an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrReplacePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrReplaceSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure sending request")
return
}
result, err = client.InsertOrReplaceResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure responding to request")
return
}
return
}
// InsertOrReplacePreparer prepares the InsertOrReplace request.
func (client Client) InsertOrReplacePreparer(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrReplaceSender sends the InsertOrReplace request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrReplaceSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrReplaceResponder handles the response to the InsertOrReplace request. The method always
// closes the http.Response Body.
func (client Client) InsertOrReplaceResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/entities/lifecycle_test.go 0000664 0000000 0000000 00000010135 14232154237 0024357 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/table/tables"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestEntitiesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := tables.NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
defer tablesClient.Delete(ctx, accountName, tableName)
entitiesClient := NewWithEnvironment(client.Environment)
entitiesClient.Client = client.PrepareWithAuthorizer(entitiesClient.Client, storageAuth)
partitionKey := "hello"
rowKey := "there"
t.Logf("[DEBUG] Inserting..")
insertInput := InsertEntityInput{
MetaDataLevel: NoMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "world",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, insertInput); err != nil {
t.Logf("Error retrieving: %s", err)
}
t.Logf("[DEBUG] Insert or Merging..")
insertOrMergeInput := InsertOrMergeEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "ther88e",
},
}
if _, err := entitiesClient.InsertOrMerge(ctx, accountName, tableName, insertOrMergeInput); err != nil {
t.Logf("Error insert/merging: %s", err)
}
t.Logf("[DEBUG] Insert or Replacing..")
insertOrReplaceInput := InsertOrReplaceEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "pandas",
},
}
if _, err := entitiesClient.InsertOrReplace(ctx, accountName, tableName, insertOrReplaceInput); err != nil {
t.Logf("Error inserting/replacing: %s", err)
}
t.Logf("[DEBUG] Querying..")
queryInput := QueryEntitiesInput{
MetaDataLevel: NoMetaData,
}
results, err := entitiesClient.Query(ctx, accountName, tableName, queryInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
if len(results.Entities) != 1 {
t.Fatalf("Expected 1 item but got %d", len(results.Entities))
}
for _, v := range results.Entities {
thisPartitionKey := v["PartitionKey"].(string)
thisRowKey := v["RowKey"].(string)
if partitionKey != thisPartitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, thisPartitionKey)
}
if rowKey != thisRowKey {
t.Fatalf("Expected Partition Key to be %q but got %q", rowKey, thisRowKey)
}
}
t.Logf("[DEBUG] Retrieving..")
getInput := GetEntityInput{
MetaDataLevel: MinimalMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
}
getResults, err := entitiesClient.Get(ctx, accountName, tableName, getInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
partitionKey2 := getResults.Entity["PartitionKey"].(string)
rowKey2 := getResults.Entity["RowKey"].(string)
if partitionKey2 != partitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, partitionKey2)
}
if rowKey2 != rowKey {
t.Fatalf("Expected Row Key to be %q but got %q", rowKey, rowKey2)
}
t.Logf("[DEBUG] Deleting..")
deleteInput := DeleteEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
}
if _, err := entitiesClient.Delete(ctx, accountName, tableName, deleteInput); err != nil {
t.Logf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2017-07-29/table/entities/models.go 0000664 0000000 0000000 00000000306 14232154237 0022643 0 ustar 00root root 0000000 0000000 package entities
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
giovanni-0.20.0/storage/2017-07-29/table/entities/query.go 0000664 0000000 0000000 00000012065 14232154237 0022532 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type QueryEntitiesInput struct {
// An optional OData filter
Filter *string
// An optional comma-separated
PropertyNamesToSelect *[]string
// An optional OData top
Top *int
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
// The Next Partition Key used to load data from a previous point
NextPartitionKey *string
// The Next Row Key used to load data from a previous point
NextRowKey *string
}
type QueryEntitiesResult struct {
autorest.Response
NextPartitionKey string
NextRowKey string
MetaData string `json:"odata.metadata,omitempty"`
Entities []map[string]interface{} `json:"value"`
}
// Query queries entities in a table and includes the $filter and $select options.
func (client Client) Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Query", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Query", "`tableName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"additionalParameters": "",
}
//PartitionKey='',RowKey=''
additionalParams := make([]string, 0)
if input.PartitionKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("PartitionKey='%s'", input.PartitionKey))
}
if input.RowKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("RowKey='%s'", input.RowKey))
}
if len(additionalParams) > 0 {
pathParameters["additionalParameters"] = autorest.Encode("path", strings.Join(additionalParams, ","))
}
queryParameters := map[string]interface{}{}
if input.Filter != nil {
queryParameters["$filter"] = autorest.Encode("query", *input.Filter)
}
if input.PropertyNamesToSelect != nil {
queryParameters["$select"] = autorest.Encode("query", strings.Join(*input.PropertyNamesToSelect, ","))
}
if input.Top != nil {
queryParameters["$top"] = autorest.Encode("query", *input.Top)
}
if input.NextPartitionKey != nil {
queryParameters["NextPartitionKey"] = *input.NextPartitionKey
}
if input.NextRowKey != nil {
queryParameters["NextRowKey"] = *input.NextRowKey
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
// GET /myaccount/Customers()?$filter=(Rating%20ge%203)%20and%20(Rating%20le%206)&$select=PartitionKey,RowKey,Address,CustomerSince
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}({additionalParameters})", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result QueryEntitiesResult, err error) {
if resp != nil && resp.Header != nil {
result.NextPartitionKey = resp.Header.Get("x-ms-continuation-NextPartitionKey")
result.NextRowKey = resp.Header.Get("x-ms-continuation-NextRowKey")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/entities/resource_id.go 0000664 0000000 0000000 00000005370 14232154237 0023671 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Entity
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName, partitionKey, rowKey string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s(PartitionKey='%s',RowKey='%s')", domain, tableName, partitionKey, rowKey)
}
type ResourceID struct {
AccountName string
TableName string
PartitionKey string
RowKey string
}
// ParseResourceID parses the specified Resource ID and returns an object which
// can be used to look up the specified Entity within the specified Table
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.Contains(uri.Path, "(") || !strings.HasSuffix(uri.Path, ")") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `tables(PartitionKey='',RowKey='')` but got %q", path)
}
// NOTE: honestly this could probably be a RegEx, but this seemed like the simplest way to
// allow these two fields to be specified in either order
indexOfBracket := strings.IndexByte(path, '(')
tableName := path[0:indexOfBracket]
// trim off the brackets
temp := strings.TrimPrefix(path, fmt.Sprintf("%s(", tableName))
temp = strings.TrimSuffix(temp, ")")
dictionary := strings.Split(temp, ",")
partitionKey := ""
rowKey := ""
for _, v := range dictionary {
split := strings.Split(v, "=")
if len(split) != 2 {
return nil, fmt.Errorf("Expected 2 segments but got %d for %q", len(split), v)
}
key := split[0]
value := strings.TrimSuffix(strings.TrimPrefix(split[1], "'"), "'")
if strings.EqualFold(key, "PartitionKey") {
partitionKey = value
} else if strings.EqualFold(key, "RowKey") {
rowKey = value
} else {
return nil, fmt.Errorf("Unexpected Key %q", key)
}
}
if partitionKey == "" {
return nil, fmt.Errorf("Expected a PartitionKey but didn't get one")
}
if rowKey == "" {
return nil, fmt.Errorf("Expected a RowKey but didn't get one")
}
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
PartitionKey: partitionKey,
RowKey: rowKey,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/table/entities/resource_id_test.go 0000664 0000000 0000000 00000005012 14232154237 0024721 0 ustar 00root root 0000000 0000000 package entities
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1", "partition1", "row1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
if actual.PartitionKey != "partition1" {
t.Fatalf("Expected Partition Key to be `partition1` but got %q", actual.PartitionKey)
}
if actual.RowKey != "row1" {
t.Fatalf("Expected Row Key to be `row1` but got %q", actual.RowKey)
}
}
}
giovanni-0.20.0/storage/2017-07-29/table/entities/version.go 0000664 0000000 0000000 00000000466 14232154237 0023054 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2017-07-29/table/tables/ 0000775 0000000 0000000 00000000000 14232154237 0020460 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2017-07-29/table/tables/README.md 0000664 0000000 0000000 00000001550 14232154237 0021740 0 ustar 00root root 0000000 0000000 ## Table Storage Tables SDK for API version 2017-07-29
This package allows you to interact with the Tables Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2017-07-29/table/tables"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
tablesClient := tables.New()
tablesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
if _, err := tablesClient.Insert(ctx, accountName, tableName); err != nil {
return fmt.Errorf("Error creating Table: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2017-07-29/table/tables/acl_get.go 0000664 0000000 0000000 00000005654 14232154237 0022417 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL returns the Access Control List for the specified Table
func (client Client) GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`tableName` cannot be an empty string.")
}
req, err := client.GetACLPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/tables/acl_set.go 0000664 0000000 0000000 00000006062 14232154237 0022425 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"encoding/xml"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List for the specified Table
func (client Client) SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`tableName` cannot be an empty string.")
}
req, err := client.SetACLPreparer(ctx, accountName, tableName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/tables/client.go 0000664 0000000 0000000 00000001126 14232154237 0022265 0 ustar 00root root 0000000 0000000 package tables
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2017-07-29/table/tables/create.go 0000664 0000000 0000000 00000005571 14232154237 0022262 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type createTableRequest struct {
TableName string `json:"TableName"`
}
// Create creates a new table in the storage account.
func (client Client) Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Create", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Create", "`tableName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// NOTE: we could support returning metadata here, but it doesn't appear to be directly useful
// vs making a request using the Get methods as-necessary?
"Accept": "application/json;odata=nometadata",
"Prefer": "return-no-content",
}
body := createTableRequest{
TableName: tableName,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithJSON(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/tables/delete.go 0000664 0000000 0000000 00000005260 14232154237 0022254 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified table and any data it contains.
func (client Client) Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Delete", "`tableName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/tables/exists.go 0000664 0000000 0000000 00000005304 14232154237 0022330 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Exists checks that the specified table exists
func (client Client) Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Exists", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Exists", "`tableName` cannot be an empty string.")
}
req, err := client.ExistsPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", nil, "Failure preparing request")
return
}
resp, err := client.ExistsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure sending request")
return
}
result, err = client.ExistsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure responding to request")
return
}
return
}
// ExistsPreparer prepares the Exists request.
func (client Client) ExistsPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.AsContentType("application/xml"),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ExistsSender sends the Exists request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ExistsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ExistsResponder handles the response to the Exists request. The method always
// closes the http.Response Body.
func (client Client) ExistsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/tables/lifecycle_test.go 0000664 0000000 0000000 00000007175 14232154237 0024017 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestTablesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
// first look it up directly and confirm it's there
t.Logf("[DEBUG] Checking if Table exists..")
if _, err := tablesClient.Exists(ctx, accountName, tableName); err != nil {
t.Fatalf("Error checking if Table %q exists: %s", tableName, err)
}
// then confirm it exists in the Query too
t.Logf("[DEBUG] Querying for Tables..")
result, err := tablesClient.Query(ctx, accountName, NoMetaData)
if err != nil {
t.Fatalf("Error retrieving Tables: %s", err)
}
found := false
for _, v := range result.Tables {
log.Printf("[DEBUG] Table: %q", v.TableName)
if v.TableName == tableName {
found = true
}
}
if !found {
t.Fatalf("%q was not found in the Query response!", tableName)
}
t.Logf("[DEBUG] Setting ACL's for Table %q..", tableName)
acls := []SignedIdentifier{
{
Id: "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=",
AccessPolicy: AccessPolicy{
Permission: "raud",
Start: "2020-11-26T08:49:37.0000000Z",
Expiry: "2020-11-27T08:49:37.0000000Z",
},
},
}
if _, err := tablesClient.SetACL(ctx, accountName, tableName, acls); err != nil {
t.Fatalf("Error setting ACLs: %s", err)
}
t.Logf("[DEBUG] Retrieving ACL's for Table %q..", tableName)
retrievedACLs, err := tablesClient.GetACL(ctx, accountName, tableName)
if err != nil {
t.Fatalf("Error retrieving ACLs: %s", err)
}
if len(retrievedACLs.SignedIdentifiers) != len(acls) {
t.Fatalf("Expected %d but got %q ACLs", len(retrievedACLs.SignedIdentifiers), len(acls))
}
for i, retrievedAcl := range retrievedACLs.SignedIdentifiers {
expectedAcl := acls[i]
if retrievedAcl.Id != expectedAcl.Id {
t.Fatalf("Expected ID to be %q but got %q", retrievedAcl.Id, expectedAcl.Id)
}
if retrievedAcl.AccessPolicy.Start != expectedAcl.AccessPolicy.Start {
t.Fatalf("Expected Start to be %q but got %q", retrievedAcl.AccessPolicy.Start, expectedAcl.AccessPolicy.Start)
}
if retrievedAcl.AccessPolicy.Expiry != expectedAcl.AccessPolicy.Expiry {
t.Fatalf("Expected Expiry to be %q but got %q", retrievedAcl.AccessPolicy.Expiry, expectedAcl.AccessPolicy.Expiry)
}
if retrievedAcl.AccessPolicy.Permission != expectedAcl.AccessPolicy.Permission {
t.Fatalf("Expected Permission to be %q but got %q", retrievedAcl.AccessPolicy.Permission, expectedAcl.AccessPolicy.Permission)
}
}
t.Logf("[DEBUG] Deleting Table %q..", tableName)
if _, err := tablesClient.Delete(ctx, accountName, tableName); err != nil {
t.Fatalf("Error deleting %q: %s", tableName, err)
}
}
giovanni-0.20.0/storage/2017-07-29/table/tables/models.go 0000664 0000000 0000000 00000001324 14232154237 0022272 0 ustar 00root root 0000000 0000000 package tables
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
type GetResultItem struct {
TableName string `json:"TableName"`
// Optional, depending on the MetaData Level
ODataType string `json:"odata.type,omitempty"`
ODataID string `json:"odata.id,omitEmpty"`
ODataEditLink string `json:"odata.editLink,omitEmpty"`
}
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2017-07-29/table/tables/query.go 0000664 0000000 0000000 00000005430 14232154237 0022156 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetResult struct {
autorest.Response
MetaData string `json:"odata.metadata,omitempty"`
Tables []GetResultItem `json:"value"`
}
// Query returns a list of tables under the specified account.
func (client Client) Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Query", "`accountName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, metaDataLevel)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (*http.Request, error) {
// NOTE: whilst this supports ContinuationTokens and 'Top'
// it appears that 'Skip' returns a '501 Not Implemented'
// as such, we intentionally don't support those right now
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", metaDataLevel),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result GetResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2017-07-29/table/tables/resource_id.go 0000664 0000000 0000000 00000003112 14232154237 0023307 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Table
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/Tables('%s')", domain, tableName)
}
type ResourceID struct {
AccountName string
TableName string
}
// ParseResourceID parses the Resource ID and returns an object which
// can be used to interact with the Table within the specified Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.table.core.windows.net/Table('foo')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.HasPrefix(path, "Tables('") || !strings.HasSuffix(path, "')") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `Tables('name')` but got %q", path)
}
// strip off the `Table('')`
tableName := strings.TrimPrefix(uri.Path, "/Tables('")
tableName = strings.TrimSuffix(tableName, "')")
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
}, nil
}
giovanni-0.20.0/storage/2017-07-29/table/tables/resource_id_test.go 0000664 0000000 0000000 00000004010 14232154237 0024344 0 ustar 00root root 0000000 0000000 package tables
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
}
}
giovanni-0.20.0/storage/2017-07-29/table/tables/version.go 0000664 0000000 0000000 00000000464 14232154237 0022500 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2017-07-29"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/ 0000775 0000000 0000000 00000000000 14232154237 0016113 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/README.md 0000664 0000000 0000000 00000001112 14232154237 0017365 0 ustar 00root root 0000000 0000000 # Storage API Version 2018-03-28
The following API's are supported by this SDK - more information about each SDK can be found within the README in each package.
## Blob Storage
- [Blobs API](blob/blobs)
- [Containers API](blob/containers)
## DataLakeStore Gen2
- [FileSystems API](datalakestore/filesystems)
## File Storage
- [Directories API](file/directories)
- [Files API](file/files)
- [Shares API](file/shares)
## Queue Storage
- [Queues API](queue/queues)
- [Messages API](queue/messages)
## Table Storage
- [Entities API](table/entities)
- [Tables API](table/tables)
giovanni-0.20.0/storage/2018-03-28/blob/ 0000775 0000000 0000000 00000000000 14232154237 0017031 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/blob/blobs/ 0000775 0000000 0000000 00000000000 14232154237 0020132 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/blob/blobs/README.md 0000664 0000000 0000000 00000002263 14232154237 0021414 0 ustar 00root root 0000000 0000000 ## Blob Storage Blobs SDK for API version 2018-03-28
This package allows you to interact with the Blobs Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/blobs"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
fileName := "example-large-file.iso"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
blobClient := blobs.New()
blobClient.Client.Authorizer = storageAuth
ctx := context.TODO()
copyInput := blobs.CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/blob/blobs/append_block.go 0000664 0000000 0000000 00000014462 14232154237 0023111 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AppendBlockInput struct {
// 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 an AppendPositionConditionNotMet
// error (HTTP status code 412 – Precondition Failed)
BlobConditionAppendPosition *int64
// 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
// an MaxBlobSizeConditionNotMet error (HTTP status code 412 – Precondition Failed).
BlobConditionMaxSize *int64
// The Bytes which should be appended to the end of this Append Blob.
// This can either be nil, which creates an empty blob, or a byte array
Content *[]byte
// An MD5 hash of the block content.
// This hash is used to verify the integrity of the block during transport.
// When this header is specified, the storage service compares the hash of the content
// that has arrived with this header value.
//
// Note that this MD5 hash is not stored with the blob.
// If the two hashes do not match, the operation will fail with error code 400 (Bad Request).
ContentMD5 *string
// Required if the blob has an active lease.
// To perform this operation on a blob with an active lease, specify the valid lease ID for this header.
LeaseID *string
}
type AppendBlockResult struct {
autorest.Response
BlobAppendOffset string
BlobCommittedBlockCount int64
ContentMD5 string
ETag string
LastModified string
}
// AppendBlock commits a new block of data to the end of an existing append blob.
func (client Client) AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) > (4*1024*1024) {
return result, validation.NewError("files.Client", "PutByteRange", "`input.Content` must be at most 4MB.")
}
req, err := client.AppendBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", nil, "Failure preparing request")
return
}
resp, err := client.AppendBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure sending request")
return
}
result, err = client.AppendBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure responding to request")
return
}
return
}
// AppendBlockPreparer prepares the AppendBlock request.
func (client Client) AppendBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "appendblock"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.BlobConditionAppendPosition != nil {
headers["x-ms-blob-condition-appendpos"] = *input.BlobConditionAppendPosition
}
if input.BlobConditionMaxSize != nil {
headers["x-ms-blob-condition-maxsize"] = *input.BlobConditionMaxSize
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AppendBlockSender sends the AppendBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AppendBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AppendBlockResponder handles the response to the AppendBlock request. The method always
// closes the http.Response Body.
func (client Client) AppendBlockResponder(resp *http.Response) (result AppendBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobAppendOffset = resp.Header.Get("x-ms-blob-append-offset")
result.ContentMD5 = resp.Header.Get("ETag")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
if v := resp.Header.Get("x-ms-blob-committed-block-count"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
result.BlobCommittedBlockCount = int64(i)
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/blob_append_test.go 0000664 0000000 0000000 00000011330 14232154237 0023763 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestAppendBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Append Blob..")
if _, err := blobClient.PutAppendBlob(ctx, accountName, containerName, fileName, PutAppendBlobInput{}); err != nil {
t.Fatalf("Error putting append blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 0 {
t.Fatalf("Expected Content-Length to be 0 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending First Block..")
appendInput := AppendBlockInput{
Content: &[]byte{
12,
48,
93,
76,
29,
10,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending first block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 6 {
t.Fatalf("Expected Content-Length to be 6 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending Second Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
92,
62,
64,
47,
83,
77,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Second block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 12 {
t.Fatalf("Expected Content-Length to be 12 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Acquiring Lease..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error acquiring Lease: %s", err)
}
t.Logf("[DEBUG] Lease ID is %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Appending Third Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
64,
35,
28,
93,
11,
23,
},
LeaseID: &leaseDetails.LeaseID,
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Third block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 18 {
t.Fatalf("Expected Content-Length to be 18 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Breaking Lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseDetails.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
t.Logf("[DEBUG] Deleting Lease..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/blob_page_test.go 0000664 0000000 0000000 00000005541 14232154237 0023437 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPageBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Page Blob..")
fileSize := int64(10240000)
if _, err := blobClient.PutPageBlob(ctx, accountName, containerName, fileName, PutPageBlobInput{
BlobContentLengthBytes: fileSize,
}); err != nil {
t.Fatalf("Error putting page blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != fileSize {
t.Fatalf("Expected Content-Length to be %d but it was %d", fileSize, props.ContentLength)
}
for iteration := 1; iteration <= 3; iteration++ {
t.Logf("[DEBUG] Putting Page %d of 3..", iteration)
byteArray := func() []byte {
o := make([]byte, 0)
for i := 0; i < 512; i++ {
o = append(o, byte(i))
}
return o
}()
startByte := int64(512 * iteration)
endByte := int64(startByte + 511)
putPageInput := PutPageUpdateInput{
StartByte: startByte,
EndByte: endByte,
Content: byteArray,
}
if _, err := blobClient.PutPageUpdate(ctx, accountName, containerName, fileName, putPageInput); err != nil {
t.Fatalf("Error putting page: %s", err)
}
}
t.Logf("[DEBUG] Deleting..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/client.go 0000664 0000000 0000000 00000001117 14232154237 0021737 0 ustar 00root root 0000000 0000000 package blobs
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/copy.go 0000664 0000000 0000000 00000022706 14232154237 0021442 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the name of the source blob or file.
// Beginning with version 2012-02-12, this value may be a URL of up to 2 KB in length that specifies a blob.
// The value should be URL-encoded as it would appear in a request URI.
// A source blob in the same storage account can be authenticated via Shared Key.
// However, if the source is a blob in another account,
// the source blob must either be public or must be authenticated via a shared access signature.
// If the source blob is public, no authentication is required to perform the copy operation.
//
// Beginning with version 2015-02-21, the source object may be a file in the Azure File service.
// If the source object is a file that is to be copied to a blob, then the source file must be authenticated
// using a shared access signature, whether it resides in the same account or in a different account.
//
// Only storage accounts created on or after June 7th, 2012 allow the Copy Blob operation to
// copy from another storage account.
CopySource string
// The ID of the Lease
// Required if the destination blob has an active lease.
// The lease ID specified for this header must match the lease ID of the destination blob.
// If the request does not include the lease ID or it is not valid,
// the operation fails with status code 412 (Precondition Failed).
//
// If this header is specified and the destination blob does not currently have an active lease,
// the operation will also fail with status code 412 (Precondition Failed).
LeaseID *string
// The ID of the Lease on the Source Blob
// Specify to perform the Copy Blob operation only if the lease ID matches the active lease ID of the source blob.
SourceLeaseID *string
// For page blobs on a premium account only. Specifies the tier to be set on the target blob
AccessTier *AccessTier
// 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.
MetaData map[string]string
// An ETag value.
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value matches the ETag value for an existing destination blob.
// If the ETag for the destination blob does not match the ETag specified for If-Match,
// the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value, or the wildcard character (*).
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value does not match the ETag value for the destination blob.
// Specify the wildcard character (*) to perform the operation only if the destination blob does not exist.
// If the specified condition isn't met, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has been modified since the specified date/time.
// If the destination blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has not been modified since the specified date/time.
// If the destination blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value.
// Specify this conditional header to copy the source blob only if its ETag matches the value specified.
// If the ETag values do not match, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfMatch *string
// An ETag value.
// Specify this conditional header to copy the blob only if its ETag does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has been modified
// since the specified date/time.
// If the source blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has not been modified
// since the specified date/time.
// If the source blob has been modified, the Blob service returns status code 412 (Precondition Failed).
// This header cannot be specified if the source is an Azure File.
SourceIfUnmodifiedSince *string
}
type CopyResult struct {
autorest.Response
CopyID string
CopyStatus string
}
// Copy copies a blob to a destination within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
req, err := client.CopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": autorest.Encode("header", input.CopySource),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SourceLeaseID != nil {
headers["x-ms-source-lease-id"] = *input.SourceLeaseID
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.SourceIfMatch != nil {
headers["x-ms-source-if-match"] = *input.SourceIfMatch
}
if input.SourceIfNoneMatch != nil {
headers["x-ms-source-if-none-match"] = *input.SourceIfNoneMatch
}
if input.SourceIfModifiedSince != nil {
headers["x-ms-source-if-modified-since"] = *input.SourceIfModifiedSince
}
if input.SourceIfUnmodifiedSince != nil {
headers["x-ms-source-if-unmodified-since"] = *input.SourceIfUnmodifiedSince
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/copy_abort.go 0000664 0000000 0000000 00000007451 14232154237 0022631 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AbortCopyInput struct {
// The Copy ID which should be aborted
CopyID string
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// AbortCopy aborts a pending Copy Blob operation, and leaves a destination blob with zero length and full metadata.
func (client Client) AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`blobName` cannot be an empty string.")
}
if input.CopyID == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`input.CopyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", input.CopyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/copy_and_wait.go 0000664 0000000 0000000 00000002050 14232154237 0023276 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"time"
)
// CopyAndWait copies a blob to a destination within the storage account and waits for it to finish copying.
func (client Client) CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error {
if _, err := client.Copy(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
for true {
getInput := GetPropertiesInput{
LeaseID: input.LeaseID,
}
getResult, err := client.GetProperties(ctx, accountName, containerName, blobName, getInput)
if err != nil {
return fmt.Errorf("")
}
switch getResult.CopyStatus {
case Aborted:
return fmt.Errorf("Copy was aborted: %s", getResult.CopyStatusDescription)
case Failed:
return fmt.Errorf("Copy failed: %s", getResult.CopyStatusDescription)
case Success:
return nil
case Pending:
time.Sleep(pollingInterval)
continue
}
}
return fmt.Errorf("Unexpected error waiting for the copy to complete")
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/copy_test.go 0000664 0000000 0000000 00000012644 14232154237 0022501 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCopyFromExistingFile(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
copiedFileName := "copied.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Duplicating that file..")
copiedInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetBlobEndpoint(blobClient.BaseURI, accountName), containerName, fileName),
}
if err := blobClient.CopyAndWait(ctx, accountName, containerName, copiedFileName, copiedInput, refreshInterval); err != nil {
t.Fatalf("Error duplicating file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Original File..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the original file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Copied File..")
copiedProps, err := blobClient.GetProperties(ctx, accountName, containerName, copiedFileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the copied file: %s", err)
}
if props.ContentLength != copiedProps.ContentLength {
t.Fatalf("Expected the content length to be %d but it was %d", props.ContentLength, copiedProps.ContentLength)
}
t.Logf("[DEBUG] Deleting copied file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, copiedFileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
t.Logf("[DEBUG] Deleting original file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
func TestCopyFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
if props.ContentLength == 0 {
t.Fatalf("Expected the file to be there but looks like it isn't: %d", props.ContentLength)
}
t.Logf("[DEBUG] Deleting file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/delete.go 0000664 0000000 0000000 00000007057 14232154237 0021734 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteInput struct {
// Should any Snapshots for this Blob also be deleted?
// If the Blob has Snapshots and this is set to False a 409 Conflict will be returned
DeleteSnapshots bool
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// Delete marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`blobName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.DeleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/delete_snapshot.go 0000664 0000000 0000000 00000007675 14232154237 0023661 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The DateTime of the Snapshot which should be marked for Deletion
SnapshotDateTime string
}
// DeleteSnapshot marks a single Snapshot of a Blob for Deletion based on it's DateTime, which will be deleted during the next Garbage Collection cycle.
func (client Client) DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`blobName` cannot be an empty string.")
}
if input.SnapshotDateTime == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`input.SnapshotDateTime` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotDateTime),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/delete_snapshots.go 0000664 0000000 0000000 00000007161 14232154237 0024032 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotsInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// DeleteSnapshots marks all Snapshots of a Blob for Deletion, which will be deleted during the next Garbage Collection Cycle.
func (client Client) DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`blobName` cannot be an empty string.")
}
req, err := client.DeleteSnapshotsPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotsPreparer prepares the DeleteSnapshots request.
func (client Client) DeleteSnapshotsPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// only delete the snapshots but leave the blob as-is
"x-ms-delete-snapshots": "only",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotsSender sends the DeleteSnapshots request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotsResponder handles the response to the DeleteSnapshots request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/get.go 0000664 0000000 0000000 00000007552 14232154237 0021251 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetResult struct {
autorest.Response
Contents []byte
}
// Get reads or downloads a blob from the system, including its metadata and properties.
func (client Client) Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Get", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Get", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Get", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Get", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "Get", "`input.LeaseID` should either be specified or nil, not an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "Get", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, containerName, blobName string, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil {
result.Contents = make([]byte, resp.ContentLength)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/get_block_list.go 0000664 0000000 0000000 00000010765 14232154237 0023456 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetBlockListInput struct {
BlockListType BlockListType
LeaseID *string
}
type GetBlockListResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
// A list of blocks which have been committed
CommittedBlocks CommittedBlocks `xml:"CommittedBlocks,omitempty"`
// A list of blocks which have not yet been committed
UncommittedBlocks UncommittedBlocks `xml:"UncommittedBlocks,omitempty"`
}
// GetBlockList retrieves the list of blocks that have been uploaded as part of a block blob.
func (client Client) GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.GetBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", nil, "Failure preparing request")
return
}
resp, err := client.GetBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure sending request")
return
}
result, err = client.GetBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure responding to request")
return
}
return
}
// GetBlockListPreparer prepares the GetBlockList request.
func (client Client) GetBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"blocklisttype": autorest.Encode("query", string(input.BlockListType)),
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetBlockListSender sends the GetBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetBlockListResponder handles the response to the GetBlockList request. The method always
// closes the http.Response Body.
func (client Client) GetBlockListResponder(resp *http.Response) (result GetBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/get_page_ranges.go 0000664 0000000 0000000 00000011500 14232154237 0023570 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPageRangesInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetPageRangesResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
PageRanges []PageRange `xml:"PageRange"`
}
type PageRange struct {
// The start byte offset for this range, inclusive
Start int64 `xml:"Start"`
// The end byte offset for this range, inclusive
End int64 `xml:"End"`
}
// GetPageRanges returns the list of valid page ranges for a page blob or snapshot of a page blob.
func (client Client) GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`blobName` cannot be an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPageRangesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", nil, "Failure preparing request")
return
}
resp, err := client.GetPageRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure sending request")
return
}
result, err = client.GetPageRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure responding to request")
return
}
return
}
// GetPageRangesPreparer prepares the GetPageRanges request.
func (client Client) GetPageRangesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "pagelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPageRangesSender sends the GetPageRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPageRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPageRangesResponder handles the response to the GetPageRanges request. The method always
// closes the http.Response Body.
func (client Client) GetPageRangesResponder(resp *http.Response) (result GetPageRangesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/incremental_copy_blob.go 0000664 0000000 0000000 00000010703 14232154237 0025013 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type IncrementalCopyBlobInput struct {
CopySource string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
}
// IncrementalCopyBlob 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.
func (client Client) IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`input.CopySource` cannot be an empty string.")
}
req, err := client.IncrementalCopyBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", nil, "Failure preparing request")
return
}
resp, err := client.IncrementalCopyBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure sending request")
return
}
result, err = client.IncrementalCopyBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure responding to request")
return
}
return
}
// IncrementalCopyBlobPreparer prepares the IncrementalCopyBlob request.
func (client Client) IncrementalCopyBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "incrementalcopy"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// IncrementalCopyBlobSender sends the IncrementalCopyBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) IncrementalCopyBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// IncrementalCopyBlobResponder handles the response to the IncrementalCopyBlob request. The method always
// closes the http.Response Body.
func (client Client) IncrementalCopyBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/lease_acquire.go 0000664 0000000 0000000 00000011502 14232154237 0023262 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput struct {
// The ID of the existing Lease, if leased
LeaseID *string
// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires.
// A non-infinite lease can be between 15 and 60 seconds
LeaseDuration int
// The Proposed new ID for the Lease
ProposedLeaseID *string
}
type AcquireLeaseResult struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a blob for write and delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseID` cannot be an empty string, if specified.")
}
if input.ProposedLeaseID != nil && *input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.ProposedLeaseID` cannot be an empty string, if specified.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.ProposedLeaseID != nil {
headers["x-ms-proposed-lease-id"] = input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResult, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/lease_break.go 0000664 0000000 0000000 00000010614 14232154237 0022720 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks an existing lock on a blob using the LeaseID.
func (client Client) BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/lease_change.go 0000664 0000000 0000000 00000007777 14232154237 0023101 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes an existing lock on a blob for another lock.
func (client Client) ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`blobName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/lease_release.go 0000664 0000000 0000000 00000006720 14232154237 0023257 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases a lock based on the Lease ID.
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/lease_renew.go 0000664 0000000 0000000 00000006555 14232154237 0022765 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
func (client Client) RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/lease_test.go 0000664 0000000 0000000 00000007152 14232154237 0022616 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLeaseLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
defer blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{})
// Test begins here
t.Logf("[DEBUG] Acquiring Lease..")
leaseInput := AcquireLeaseInput{
LeaseDuration: -1,
}
leaseInfo, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Changing Lease..")
changeLeaseInput := ChangeLeaseInput{
ExistingLeaseID: leaseInfo.LeaseID,
ProposedLeaseID: "31f5bb01-cdd9-4166-bcdc-95186076bde0",
}
changeLeaseResult, err := blobClient.ChangeLease(ctx, accountName, containerName, fileName, changeLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
t.Logf("[DEBUG] New Lease ID: %q", changeLeaseResult.LeaseID)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, changeLeaseResult.LeaseID); err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Acquiring a new lease..")
leaseInput = AcquireLeaseInput{
LeaseDuration: 30,
}
leaseInfo, err = blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Renewing lease..")
if _, err := blobClient.RenewLease(ctx, accountName, containerName, fileName, leaseInfo.LeaseID); err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
t.Logf("[DEBUG] Breaking lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseInfo.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/lifecycle_test.go 0000664 0000000 0000000 00000012554 14232154237 0023466 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Blob Properties..")
details, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 0 {
t.Fatalf("Expected there to be no items of metadata but got %d", len(details.MetaData))
}
t.Logf("[DEBUG] Checking it's returned in the List API..")
listInput := containers.ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 1 {
t.Fatalf("Expected there to be 1 blob in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Setting MetaData..")
metaDataInput := SetMetaDataInput{
MetaData: map[string]string{
"hello": "there",
},
}
if _, err := blobClient.SetMetaData(ctx, accountName, containerName, fileName, metaDataInput); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 1 {
t.Fatalf("Expected there to be 1 item of metadata but got %d", len(details.MetaData))
}
if details.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", details.MetaData["there"])
}
t.Logf("[DEBUG] Retrieving the Block List..")
getBlockListInput := GetBlockListInput{
BlockListType: All,
}
blockList, err := blobClient.GetBlockList(ctx, accountName, containerName, fileName, getBlockListInput)
if err != nil {
t.Fatalf("Error retrieving Block List: %s", err)
}
// since this is a copy from an existing file, all blocks should be present
if len(blockList.CommittedBlocks.Blocks) == 0 {
t.Fatalf("Expected there to be committed blocks but there weren't!")
}
if len(blockList.UncommittedBlocks.Blocks) != 0 {
t.Fatalf("Expected all blocks to be committed but got %d uncommitted blocks", len(blockList.UncommittedBlocks.Blocks))
}
t.Logf("[DEBUG] Changing the Access Tiers..")
tiers := []AccessTier{
Hot,
Cool,
Archive,
}
for _, tier := range tiers {
t.Logf("[DEBUG] Updating the Access Tier to %q..", string(tier))
if _, err := blobClient.SetTier(ctx, accountName, containerName, fileName, tier); err != nil {
t.Fatalf("Error setting the Access Tier: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
if details.AccessTier != tier {
t.Fatalf("Expected the AccessTier to be %q but got %q", tier, details.AccessTier)
}
}
t.Logf("[DEBUG] Deleting Blob")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/metadata_set.go 0000664 0000000 0000000 00000007724 14232154237 0023126 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SetMetaDataInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// Any metadata which should be added to this blob
MetaData map[string]string
}
// SetMetaData marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "GetProperties", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/models.go 0000664 0000000 0000000 00000002714 14232154237 0021750 0 ustar 00root root 0000000 0000000 package blobs
type AccessTier string
var (
Archive AccessTier = "Archive"
Cool AccessTier = "Cool"
Hot AccessTier = "Hot"
)
type ArchiveStatus string
var (
None ArchiveStatus = ""
RehydratePendingToCool ArchiveStatus = "rehydrate-pending-to-cool"
RehydratePendingToHot ArchiveStatus = "rehydrate-pending-to-hot"
)
type BlockListType string
var (
All BlockListType = "all"
Committed BlockListType = "committed"
Uncommitted BlockListType = "uncommitted"
)
type Block struct {
// The base64-encoded Block ID
Name string `xml:"Name"`
// The size of the Block in Bytes
Size int64 `xml:"Size"`
}
type BlobType string
var (
AppendBlob BlobType = "AppendBlob"
BlockBlob BlobType = "BlockBlob"
PageBlob BlobType = "PageBlob"
)
type CommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
type CopyStatus string
var (
Aborted CopyStatus = "aborted"
Failed CopyStatus = "failed"
Pending CopyStatus = "pending"
Success CopyStatus = "success"
)
type LeaseDuration string
var (
Fixed LeaseDuration = "fixed"
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
type UncommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/properties_get.go 0000664 0000000 0000000 00000031314 14232154237 0023516 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
type GetPropertiesResult struct {
autorest.Response
// The tier of page blob on a premium storage account or tier of block blob on blob storage or general purpose v2 account.
AccessTier AccessTier
// This gives the last time tier was changed on the object.
// This header is returned only if tier on block blob was ever set.
// The date format follows RFC 1123
AccessTierChangeTime string
// For page blobs on a premium storage account only.
// If the access tier is not explicitly set on the blob, the tier is inferred based on its content length
// and this header will be returned with true value.
// For block blobs on Blob Storage or general purpose v2 account, if the blob does not have the access tier
// set then we infer the tier from the storage account properties. This header is set only if the block blob
// tier is inferred
AccessTierInferred bool
// For blob storage or general purpose v2 account.
// If the blob is being rehydrated and is not complete then this header is returned indicating
// that rehydrate is pending and also tells the destination tier
ArchiveStatus ArchiveStatus
// The number of committed blocks present in the blob.
// This header is returned only for append blobs.
BlobCommittedBlockCount string
// The current sequence number for a page blob.
// This header is not returned for block blobs or append blobs.
// This header is not returned for block blobs.
BlobSequenceNumber string
// The blob type.
BlobType BlobType
// If the Cache-Control request header has previously been set for the blob, that value is returned in this header.
CacheControl string
// The Content-Disposition response header field conveys additional information about how to process
// the response payload, and also can be used to attach additional metadata.
// For example, if set to attachment, it indicates that the user-agent should not display the response,
// but instead show a Save As dialog.
ContentDisposition string
// If the Content-Encoding request header has previously been set for the blob,
// that value is returned in this header.
ContentEncoding string
// If the Content-Language request header has previously been set for the blob,
// that value is returned in this header.
ContentLanguage string
// The size of the blob in bytes.
// For a page blob, this header returns the value of the x-ms-blob-content-length header stored with the blob.
ContentLength int64
// The content type specified for the blob.
// If no content type was specified, the default content type is `application/octet-stream`.
ContentType string
// If the Content-MD5 header has been set for the blob, this response header is returned so that
// the client can check for message content integrity.
ContentMD5 string
// Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob.
// This value can specify the time of a completed, aborted, or failed copy attempt.
// This header does not appear if a copy is pending, if this blob has never been the
// destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob
// operation using Set Blob Properties, Put Blob, or Put Block List.
CopyCompletionTime string
// Included if the blob is incremental copy blob or incremental copy snapshot, if x-ms-copy-status is success.
// Snapshot time of the last successful incremental copy snapshot for this blob
CopyDestinationSnapshot string
// String identifier for the last attempted Copy Blob operation where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyID string
// Contains the number of bytes copied and the total bytes in the source in the last attempted
// Copy Blob operation where this blob was the destination blob.
// Can show between 0 and Content-Length bytes copied.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyProgress string
// URL up to 2 KB in length that specifies the source blob used in the last attempted Copy Blob operation
// where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List
CopySource string
// State of the copy operation identified by x-ms-copy-id, with these values:
// - success: Copy completed successfully.
// - pending: Copy is in progress.
// Check x-ms-copy-status-description if intermittent, non-fatal errors
// impede copy progress but don’t cause failure.
// - aborted: Copy was ended by Abort Copy Blob.
// - failed: Copy failed. See x-ms- copy-status-description for failure details.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a completed Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatus CopyStatus
// Describes cause of fatal or non-fatal copy operation failure.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatusDescription string
// The date/time at which the blob was created. The date format follows RFC 1123
CreationTime string
// The ETag contains a value that you can use to perform operations conditionally
ETag string
// Included if the blob is incremental copy blob.
IncrementalCopy bool
// The date/time that the blob was last modified. The date format follows RFC 1123.
LastModified string
// When a blob is leased, specifies whether the lease is of infinite or fixed duration
LeaseDuration LeaseDuration
// The lease state of the blob
LeaseState LeaseState
LeaseStatus LeaseStatus
// A set of name-value pairs that correspond to the user-defined metadata associated with this blob
MetaData map[string]string
// Is the Storage Account encrypted using server-side encryption? This should always return true
ServerEncrypted bool
}
// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the blob
func (client Client) GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.AccessTier = AccessTier(resp.Header.Get("x-ms-access-tier"))
result.AccessTierChangeTime = resp.Header.Get(" x-ms-access-tier-change-time")
result.ArchiveStatus = ArchiveStatus(resp.Header.Get(" x-ms-archive-status"))
result.BlobCommittedBlockCount = resp.Header.Get("x-ms-blob-committed-block-count")
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.BlobType = BlobType(resp.Header.Get("x-ms-blob-type"))
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.CopyDestinationSnapshot = resp.Header.Get("x-ms-copy-destination-snapshot")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = CopyStatus(resp.Header.Get("x-ms-copy-status"))
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CreationTime = resp.Header.Get("x-ms-creation-time")
result.ETag = resp.Header.Get("Etag")
result.LastModified = resp.Header.Get("Last-Modified")
result.LeaseDuration = LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.MetaData = metadata.ParseFromHeaders(resp.Header)
if v := resp.Header.Get("x-ms-access-tier-inferred"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.AccessTierInferred = b
}
if v := resp.Header.Get("Content-Length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
}
result.ContentLength = int64(i)
}
if v := resp.Header.Get("x-ms-incremental-copy"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
if v := resp.Header.Get("x-ms-server-encrypted"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/properties_set.go 0000664 0000000 0000000 00000012111 14232154237 0023524 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
CacheControl *string
ContentType *string
ContentMD5 *string
ContentEncoding *string
ContentLanguage *string
LeaseID *string
ContentDisposition *string
ContentLength *int64
SequenceNumberAction *SequenceNumberAction
BlobSequenceNumber *string
}
type SetPropertiesResult struct {
autorest.Response
BlobSequenceNumber string
Etag string
}
// SetProperties sets system properties on the blob.
func (client Client) SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
type SequenceNumberAction string
var (
Increment SequenceNumberAction = "increment"
Max SequenceNumberAction = "max"
Update SequenceNumberAction = "update"
)
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.ContentLength != nil {
headers["x-ms-blob-content-length"] = *input.ContentLength
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SequenceNumberAction != nil {
headers["x-ms-sequence-number-action"] = string(*input.SequenceNumberAction)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result SetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.Etag = resp.Header.Get("Etag")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_append_blob.go 0000664 0000000 0000000 00000011323 14232154237 0023616 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutAppendBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutAppendBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new append blob, or updates the content of an existing blob.
func (client Client) PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutAppendBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutAppendBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutAppendBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure sending request")
return
}
result, err = client.PutAppendBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure responding to request")
return
}
return
}
// PutAppendBlobPreparer prepares the PutAppendBlob request.
func (client Client) PutAppendBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(AppendBlob),
"x-ms-version": APIVersion,
// For a page blob or an append blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutAppendBlobSender sends the PutAppendBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutAppendBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutAppendBlobResponder handles the response to the PutAppendBlob request. The method always
// closes the http.Response Body.
func (client Client) PutAppendBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_block.go 0000664 0000000 0000000 00000010100 14232154237 0022433 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockInput struct {
BlockID string
Content []byte
ContentMD5 *string
LeaseID *string
}
type PutBlockResult struct {
autorest.Response
ContentMD5 string
}
// PutBlock creates a new block to be committed as part of a blob.
func (client Client) PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.BlockID` cannot be an empty string.")
}
if len(input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.Content` cannot be empty.")
}
req, err := client.PutBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure sending request")
return
}
result, err = client.PutBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure responding to request")
return
}
return
}
// PutBlockPreparer prepares the PutBlock request.
func (client Client) PutBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Content-Length": int(len(input.Content)),
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockSender sends the PutBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockResponder handles the response to the PutBlock request. The method always
// closes the http.Response Body.
func (client Client) PutBlockResponder(resp *http.Response) (result PutBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_block_blob.go 0000664 0000000 0000000 00000011750 14232154237 0023445 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutBlockBlobInput struct {
CacheControl *string
Content *[]byte
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutBlockBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block append blob, or updates the content of an existing block blob.
func (client Client) PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`input.Content` must either be nil or not empty.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutBlockBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutBlockBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure sending request")
return
}
result, err = client.PutBlockBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure responding to request")
return
}
return
}
// PutBlockBlobPreparer prepares the PutBlockBlob request.
func (client Client) PutBlockBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(BlockBlob),
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockBlobSender sends the PutBlockBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockBlobResponder handles the response to the PutBlockBlob request. The method always
// closes the http.Response Body.
func (client Client) PutBlockBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_block_blob_file.go 0000664 0000000 0000000 00000001510 14232154237 0024435 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"io"
"os"
)
// PutBlockBlobFromFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
bytes := make([]byte, fileSize)
_, err = file.ReadAt(bytes, 0)
if err != nil {
if err != io.EOF {
return fmt.Errorf("Error reading bytes: %s", err)
}
}
input.Content = &bytes
if _, err = client.PutBlockBlob(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error putting bytes: %s", err)
}
return nil
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_block_list.go 0000664 0000000 0000000 00000012220 14232154237 0023473 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type BlockList struct {
CommittedBlockIDs []BlockID `xml:"Committed,omitempty"`
UncommittedBlockIDs []BlockID `xml:"Uncommitted,omitempty"`
LatestBlockIDs []BlockID `xml:"Latest,omitempty"`
}
type BlockID struct {
Value string `xml:",chardata"`
}
type PutBlockListInput struct {
BlockList BlockList
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
MetaData map[string]string
LeaseID *string
}
type PutBlockListResult struct {
autorest.Response
ContentMD5 string
ETag string
LastModified string
}
// PutBlockList 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.
func (client Client) PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.PutBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure sending request")
return
}
result, err = client.PutBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure responding to request")
return
}
return
}
// PutBlockListPreparer prepares the PutBlockList request.
func (client Client) PutBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(input.BlockList))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockListSender sends the PutBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockListResponder handles the response to the PutBlockList request. The method always
// closes the http.Response Body.
func (client Client) PutBlockListResponder(resp *http.Response) (result PutBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_block_url.go 0000664 0000000 0000000 00000010564 14232154237 0023333 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockFromURLInput struct {
BlockID string
CopySource string
ContentMD5 *string
LeaseID *string
Range *string
}
type PutBlockFromURLResult struct {
autorest.Response
ContentMD5 string
}
// PutBlockFromURL creates a new block to be committed as part of a blob where the contents are read from a URL
func (client Client) PutBlockFromURL(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (result PutBlockFromURLResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.BlockID` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.CopySource` cannot be an empty string.")
}
req, err := client.PutBlockFromURLPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockFromURLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure sending request")
return
}
result, err = client.PutBlockFromURLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure responding to request")
return
}
return
}
// PutBlockFromURLPreparer prepares the PutBlockFromURL request.
func (client Client) PutBlockFromURLPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.ContentMD5 != nil {
headers["x-ms-source-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Range != nil {
headers["x-ms-source-range"] = *input.Range
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockFromURLSender sends the PutBlockFromURL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockFromURLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockFromURLResponder handles the response to the PutBlockFromURL request. The method always
// closes the http.Response Body.
func (client Client) PutBlockFromURLResponder(resp *http.Response) (result PutBlockFromURLResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_page_blob.go 0000664 0000000 0000000 00000012264 14232154237 0023270 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutPageBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
BlobContentLengthBytes int64
BlobSequenceNumber *int64
AccessTier *AccessTier
}
// PutPageBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block blob, or updates the content of an existing page blob.
func (client Client) PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`blobName` cannot be an empty string.")
}
if input.BlobContentLengthBytes == 0 || input.BlobContentLengthBytes%512 != 0 {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`input.BlobContentLengthBytes` must be aligned to a 512-byte boundary.")
}
req, err := client.PutPageBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutPageBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure sending request")
return
}
result, err = client.PutPageBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure responding to request")
return
}
return
}
// PutPageBlobPreparer prepares the PutPageBlob request.
func (client Client) PutPageBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(PageBlob),
"x-ms-version": APIVersion,
// For a page blob or an page blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
// This header specifies the maximum size for the page blob, up to 8 TB.
// The page blob size must be aligned to a 512-byte boundary.
"x-ms-blob-content-length": input.BlobContentLengthBytes,
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageBlobSender sends the PutPageBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageBlobResponder handles the response to the PutPageBlob request. The method always
// closes the http.Response Body.
func (client Client) PutPageBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_page_clear.go 0000664 0000000 0000000 00000007556 14232154237 0023450 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageClearInput struct {
StartByte int64
EndByte int64
LeaseID *string
}
// PutPageClear clears a range of pages within a page blob.
func (client Client) PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.EndByte` must be greater than 0.")
}
req, err := client.PutPageClearPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", nil, "Failure preparing request")
return
}
resp, err := client.PutPageClearSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure sending request")
return
}
result, err = client.PutPageClearResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure responding to request")
return
}
return
}
// PutPageClearPreparer prepares the PutPageClear request.
func (client Client) PutPageClearPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageClearSender sends the PutPageClear request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageClearSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageClearResponder handles the response to the PutPageClear request. The method always
// closes the http.Response Body.
func (client Client) PutPageClearResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/put_page_update.go 0000664 0000000 0000000 00000012777 14232154237 0023645 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageUpdateInput struct {
StartByte int64
EndByte int64
Content []byte
IfSequenceNumberEQ *string
IfSequenceNumberLE *string
IfSequenceNumberLT *string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
LeaseID *string
}
type PutPageUpdateResult struct {
autorest.Response
BlobSequenceNumber string
ContentMD5 string
LastModified string
}
// PutPageUpdate writes a range of pages to a page blob.
func (client Client) PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.EndByte` must be greater than 0.")
}
expectedSize := (input.EndByte - input.StartByte) + 1
actualSize := int64(len(input.Content))
if expectedSize != actualSize {
return result, validation.NewError("blobs.Client", "PutPageUpdate", fmt.Sprintf("Content Size was defined as %d but got %d.", expectedSize, actualSize))
}
req, err := client.PutPageUpdatePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", nil, "Failure preparing request")
return
}
resp, err := client.PutPageUpdateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure sending request")
return
}
result, err = client.PutPageUpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure responding to request")
return
}
return
}
// PutPageUpdatePreparer prepares the PutPageUpdate request.
func (client Client) PutPageUpdatePreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
"Content-Length": int(len(input.Content)),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfSequenceNumberEQ != nil {
headers["x-ms-if-sequence-number-eq"] = *input.IfSequenceNumberEQ
}
if input.IfSequenceNumberLE != nil {
headers["x-ms-if-sequence-number-le"] = *input.IfSequenceNumberLE
}
if input.IfSequenceNumberLT != nil {
headers["x-ms-if-sequence-number-lt"] = *input.IfSequenceNumberLT
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageUpdateSender sends the PutPageUpdate request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageUpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageUpdateResponder handles the response to the PutPageUpdate request. The method always
// closes the http.Response Body.
func (client Client) PutPageUpdateResponder(resp *http.Response) (result PutPageUpdateResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/resource_id.go 0000664 0000000 0000000 00000003060 14232154237 0022763 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Blob
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName, blobName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, containerName, blobName)
}
type ResourceID struct {
AccountName string
ContainerName string
BlobName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Blob Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar/example.vhd
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
containerName := segments[0]
blobName := strings.TrimPrefix(path, containerName)
blobName = strings.TrimPrefix(blobName, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
BlobName: blobName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/resource_id_test.go 0000664 0000000 0000000 00000006670 14232154237 0024034 0 ustar 00root root 0000000 0000000 package blobs
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1", "blob1.vhd")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "blob1.vhd" {
t.Fatalf("Expected Blob Name to be `blob1.vhd` but got %q", actual.BlobName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/example/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/example/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/example/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/example/blob1.vhd",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "example/blob1.vhd" {
t.Fatalf("Expected Blob Name to be `example/blob1.vhd` but got %q", actual.BlobName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/set_tier.go 0000664 0000000 0000000 00000006325 14232154237 0022305 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetTier sets the tier on a blob.
func (client Client) SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`blobName` cannot be an empty string.")
}
req, err := client.SetTierPreparer(ctx, accountName, containerName, blobName, tier)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", nil, "Failure preparing request")
return
}
resp, err := client.SetTierSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure sending request")
return
}
result, err = client.SetTierResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure responding to request")
return
}
return
}
// SetTierPreparer prepares the SetTier request.
func (client Client) SetTierPreparer(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "tier"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-access-tier": string(tier),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetTierSender sends the SetTier request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetTierSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetTierResponder handles the response to the SetTier request. The method always
// closes the http.Response Body.
func (client Client) SetTierResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/snapshot.go 0000664 0000000 0000000 00000013463 14232154237 0022327 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// MetaData is a user-defined name-value pair associated with the blob.
// If no name-value pairs are specified, the operation will copy the base blob metadata to the snapshot.
// If one or more name-value pairs are specified, the snapshot is created with the specified metadata,
// and metadata is not copied from the base blob.
MetaData map[string]string
// A DateTime value which will only snapshot the blob if it has been modified since the specified date/time
// If the base blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value which will only snapshot the blob if it has not been modified since the specified date/time
// If the base blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value to snapshot the blob only if its ETag value matches the value specified.
// If the values do not match, the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value for this conditional header to snapshot the blob only if its ETag value
// does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
}
type SnapshotResult struct {
autorest.Response
// The ETag of the snapshot
ETag string
// A DateTime value that uniquely identifies the snapshot.
// The value of this header indicates the snapshot version,
// and may be used in subsequent requests to access the snapshot.
SnapshotDateTime string
}
// Snapshot captures a Snapshot of a given Blob
func (client Client) Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "Snapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", nil, "Failure preparing request")
return
}
resp, err := client.SnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure sending request")
return
}
result, err = client.SnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure responding to request")
return
}
return
}
// SnapshotPreparer prepares the Snapshot request.
func (client Client) SnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SnapshotSender sends the Snapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SnapshotResponder handles the response to the Snapshot request. The method always
// closes the http.Response Body.
func (client Client) SnapshotResponder(resp *http.Response) (result SnapshotResult, err error) {
if resp != nil && resp.Header != nil {
result.ETag = resp.Header.Get("ETag")
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/snapshot_get_properties.go 0000664 0000000 0000000 00000006445 14232154237 0025444 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetSnapshotPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The ID of the Snapshot which should be retrieved
SnapshotID string
}
// GetSnapshotProperties returns all user-defined metadata, standard HTTP properties, and system properties for
// the specified snapshot of a blob
func (client Client) GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`blobName` cannot be an empty string.")
}
if input.SnapshotID == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`input.SnapshotID` cannot be an empty string.")
}
req, err := client.GetSnapshotPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", nil, "Failure preparing request")
return
}
// we re-use the GetProperties methods since this is otherwise the same
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/snapshot_test.go 0000664 0000000 0000000 00000013411 14232154237 0023357 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestSnapshotLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatalf("Error creating: %s", err)
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] First Snapshot..")
firstSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{})
if err != nil {
t.Fatalf("Error taking first snapshot: %s", err)
}
t.Logf("[DEBUG] First Snapshot ID: %q", firstSnapshot.SnapshotDateTime)
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
t.Logf("[DEBUG] Second Snapshot..")
secondSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
MetaData: map[string]string{
"hello": "world",
},
})
if err != nil {
t.Fatalf("Error taking Second snapshot: %s", err)
}
t.Logf("[DEBUG] Second Snapshot ID: %q", secondSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Leasing the Blob..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
// infinite
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error leasing Blob: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Third Snapshot..")
thirdSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error taking Third snapshot: %s", err)
}
t.Logf("[DEBUG] Third Snapshot ID: %q", thirdSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, leaseDetails.LeaseID); err != nil {
t.Fatalf("Error releasing Lease: %s", err)
}
// get the properties from the blob, which should include the LastModifiedDate
t.Logf("[DEBUG] Retrieving Properties for Blob")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
// confirm that the If-Modified-None returns an error
t.Logf("[DEBUG] Third Snapshot..")
fourthSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
IfModifiedSince: &props.LastModified,
})
if err == nil {
t.Fatalf("Expected an error but didn't get one")
}
if fourthSnapshot.Response.StatusCode != http.StatusPreconditionFailed {
t.Fatalf("Expected the status code to be Precondition Failed but got: %d", fourthSnapshot.Response.StatusCode)
}
t.Logf("[DEBUG] Retrieving the Second Snapshot Properties..")
getSecondSnapshotInput := GetSnapshotPropertiesInput{
SnapshotID: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput); err != nil {
t.Fatalf("Error retrieving properties for the second snapshot: %s", err)
}
t.Logf("[DEBUG] Deleting the Second Snapshot..")
deleteSnapshotInput := DeleteSnapshotInput{
SnapshotDateTime: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.DeleteSnapshot(ctx, accountName, containerName, fileName, deleteSnapshotInput); err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Second Snapshot Properties..")
secondSnapshotProps, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput)
if err == nil {
t.Fatalf("Expected an error retrieving the snapshot but got none")
}
if secondSnapshotProps.Response.StatusCode != http.StatusNotFound {
t.Fatalf("Expected the status code to be %d but got %q", http.StatusNoContent, secondSnapshotProps.Response.StatusCode)
}
t.Logf("[DEBUG] Deleting all the snapshots..")
if _, err := blobClient.DeleteSnapshots(ctx, accountName, containerName, fileName, DeleteSnapshotsInput{}); err != nil {
t.Fatalf("Error deleting snapshots: %s", err)
}
t.Logf("[DEBUG] Deleting the Blob..")
deleteInput := DeleteInput{
DeleteSnapshots: false,
}
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, deleteInput); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/undelete.go 0000664 0000000 0000000 00000006323 14232154237 0022272 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Undelete restores the contents and metadata of soft deleted blob and any associated soft deleted snapshots.
func (client Client) Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`blobName` cannot be an empty string.")
}
req, err := client.UndeletePreparer(ctx, accountName, containerName, blobName)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", nil, "Failure preparing request")
return
}
resp, err := client.UndeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure sending request")
return
}
result, err = client.UndeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure responding to request")
return
}
return
}
// UndeletePreparer prepares the Undelete request.
func (client Client) UndeletePreparer(ctx context.Context, accountName, containerName, blobName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "undelete"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UndeleteSender sends the Undelete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UndeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UndeleteResponder handles the response to the Undelete request. The method always
// closes the http.Response Body.
func (client Client) UndeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/blobs/version.go 0000664 0000000 0000000 00000000463 14232154237 0022151 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/ 0000775 0000000 0000000 00000000000 14232154237 0021176 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/blob/containers/README.md 0000664 0000000 0000000 00000002257 14232154237 0022463 0 ustar 00root root 0000000 0000000 ## Blob Storage Container SDK for API version 2018-03-28
This package allows you to interact with the Containers Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
Note: when using the `ListBlobs` operation, only `SharedKeyLite` authentication is supported.
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/blob/containers"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
containersClient := containers.New()
containersClient.Client.Authorizer = storageAuth
ctx := context.TODO()
createInput := containers.CreateInput{
AccessLevel: containers.Private,
}
if _, err := containersClient.Create(ctx, accountName, containerName, createInput); err != nil {
return fmt.Errorf("Error creating Container: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/blob/containers/client.go 0000664 0000000 0000000 00000001632 14232154237 0023005 0 ustar 00root root 0000000 0000000 package containers
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Containers.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
func (client Client) setAccessLevelIntoHeaders(headers map[string]interface{}, level AccessLevel) map[string]interface{} {
// If this header is not included in the request, container data is private to the account owner.
if level != Private {
headers["x-ms-blob-public-access"] = string(level)
}
return headers
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/create.go 0000664 0000000 0000000 00000010233 14232154237 0022767 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies whether data in the container may be accessed publicly and the level of access
AccessLevel AccessLevel
// A name-value pair to associate with the container as metadata.
MetaData map[string]string
}
type CreateResponse struct {
autorest.Response
Error *ErrorResponse `xml:"Error"`
}
// Create creates a new container under the specified account.
// If the container with the same name already exists, the operation fails.
func (client Client) Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Create", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Create", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("containers.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, containerName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, input.AccessLevel)
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result CreateResponse, err error) {
successfulStatusCodes := []int{
http.StatusCreated,
}
if autorest.ResponseHasStatusCode(resp, successfulStatusCodes...) {
// when successful there's no response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
} else {
// however when there's an error the error's in the response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/delete.go 0000664 0000000 0000000 00000005600 14232154237 0022770 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete marks the specified container for deletion.
// The container and any blobs contained within it are later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Delete", "`containerName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, containerName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/get_properties.go 0000664 0000000 0000000 00000011677 14232154237 0024574 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// GetProperties returns the properties for this Container without a Lease
func (client Client) GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error) {
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
return client.GetPropertiesWithLeaseID(ctx, accountName, containerName, "")
}
// GetPropertiesWithLeaseID returns the properties for this Container using the specified LeaseID
func (client Client) GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`containerName` cannot be an empty string.")
}
req, err := client.GetPropertiesWithLeaseIDPreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesWithLeaseIDSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesWithLeaseIDPreparer prepares the GetPropertiesWithLeaseID request.
func (client Client) GetPropertiesWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesWithLeaseIDSender sends the GetPropertiesWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesWithLeaseIDResponder handles the response to the GetPropertiesWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesWithLeaseIDResponder(resp *http.Response) (result ContainerProperties, err error) {
if resp != nil {
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
if result.LeaseStatus == Locked {
duration := LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseDuration = &duration
}
// If this header is not returned in the response, the container is private to the account owner.
accessLevel := resp.Header.Get("x-ms-blob-public-access")
if accessLevel != "" {
result.AccessLevel = AccessLevel(accessLevel)
} else {
result.AccessLevel = Private
}
// we can't necessarily use strconv.ParseBool here since this could be nil (only in some API versions)
result.HasImmutabilityPolicy = strings.EqualFold(resp.Header.Get("x-ms-has-immutability-policy"), "true")
result.HasLegalHold = strings.EqualFold(resp.Header.Get("x-ms-has-legal-hold"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/lease_acquire.go 0000664 0000000 0000000 00000007762 14232154237 0024343 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput 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
LeaseDuration int
ProposedLeaseID string
}
type AcquireLeaseResponse struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a container for delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("containers.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName string, containerName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.ProposedLeaseID != "" {
headers["x-ms-proposed-lease-id"] = input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/lease_break.go 0000664 0000000 0000000 00000010521 14232154237 0023761 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strconv"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks a lock based on it's Lease ID
func (client Client) BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName string, containerName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result BreakLeaseResponse, err error) {
if resp != nil {
leaseRaw := resp.Header.Get("x-ms-lease-time")
if leaseRaw != "" {
i, err := strconv.Atoi(leaseRaw)
if err == nil {
result.LeaseTime = i
}
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/lease_change.go 0000664 0000000 0000000 00000007356 14232154237 0024136 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes the lock from one Lease ID to another Lease ID
func (client Client) ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName string, containerName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/lease_release.go 0000664 0000000 0000000 00000006324 14232154237 0024323 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases the lock based on the Lease ID
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/lease_renew.go 0000664 0000000 0000000 00000006251 14232154237 0024022 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// RenewLease renewes the lock based on the Lease ID
func (client Client) RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/lifecycle_test.go 0000664 0000000 0000000 00000013057 14232154237 0024531 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
// first let's test an empty container
input := CreateInput{}
_, err = containersClient.Create(ctx, accountName, containerName, input)
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
container, err := containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error retrieving: %s", err))
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if len(container.MetaData) != 0 {
t.Fatalf("Expected MetaData to be empty but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the metadata
metaData := map[string]string{
"dont": "kill-my-vibe",
}
_, err = containersClient.SetMetaData(ctx, accountName, containerName, metaData)
if err != nil {
t.Fatal(fmt.Errorf("Error updating metadata: %s", err))
}
// give azure time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.MetaData["dont"] != "kill-my-vibe" {
t.Fatalf("Expected `kill-my-vibe` but got %q", container.MetaData["dont"])
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the ACL
_, err = containersClient.SetAccessControl(ctx, accountName, containerName, Blob)
if err != nil {
t.Fatal(fmt.Errorf("Error updating ACL's: %s", err))
}
// give azure some time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if container.AccessLevel != Blob {
t.Fatalf("Expected Access Level to be Blob but got %q", container.AccessLevel)
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// acquire a lease for 30s
acquireLeaseInput := AcquireLeaseInput{
LeaseDuration: 30,
}
acquireLeaseResp, err := containersClient.AcquireLease(ctx, accountName, containerName, acquireLeaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %s", acquireLeaseResp.LeaseID)
// we should then be able to update the ID
t.Logf("[DEBUG] Changing lease..")
updateLeaseInput := ChangeLeaseInput{
ExistingLeaseID: acquireLeaseResp.LeaseID,
ProposedLeaseID: "aaaabbbb-aaaa-bbbb-cccc-aaaabbbbcccc",
}
updateLeaseResp, err := containersClient.ChangeLease(ctx, accountName, containerName, updateLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
// then renew it
_, err = containersClient.RenewLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
// and then give it a timeout
breakPeriod := 20
breakLeaseInput := BreakLeaseInput{
LeaseID: updateLeaseResp.LeaseID,
BreakPeriod: &breakPeriod,
}
breakLeaseResp, err := containersClient.BreakLease(ctx, accountName, containerName, breakLeaseInput)
if err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
if breakLeaseResp.LeaseTime == 0 {
t.Fatalf("Lease broke immediately when should have waited: %d", breakLeaseResp.LeaseTime)
}
// and finally ditch it
_, err = containersClient.ReleaseLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Listing blobs in the container..")
listInput := ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 0 {
t.Fatalf("Expected there to be no blobs in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Deleting..")
_, err = containersClient.Delete(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/list_blobs.go 0000664 0000000 0000000 00000015033 14232154237 0023663 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListBlobsInput struct {
Delimiter *string
Include *[]Dataset
Marker *string
MaxResults *int
Prefix *string
}
type ListBlobsResult struct {
autorest.Response
Delimiter string `xml:"Delimiter"`
Marker string `xml:"Marker"`
MaxResults int `xml:"MaxResults"`
NextMarker *string `xml:"NextMarker,omitempty"`
Prefix string `xml:"Prefix"`
Blobs Blobs `xml:"Blobs"`
}
type Blobs struct {
Blobs []BlobDetails `xml:"Blob"`
BlobPrefix *BlobPrefix `xml:"BlobPrefix"`
}
type BlobDetails struct {
Name string `xml:"Name"`
Deleted bool `xml:"Deleted,omitempty"`
MetaData map[string]interface{} `map:"Metadata,omitempty"`
Properties *BlobProperties `xml:"Properties,omitempty"`
Snapshot *string `xml:"Snapshot,omitempty"`
}
type BlobProperties struct {
AccessTier *string `xml:"AccessTier,omitempty"`
AccessTierInferred *bool `xml:"AccessTierInferred,omitempty"`
AccessTierChangeTime *string `xml:"AccessTierChangeTime,omitempty"`
BlobType *string `xml:"BlobType,omitempty"`
BlobSequenceNumber *string `xml:"x-ms-blob-sequence-number,omitempty"`
CacheControl *string `xml:"Cache-Control,omitempty"`
ContentEncoding *string `xml:"ContentEncoding,omitempty"`
ContentLanguage *string `xml:"Content-Language,omitempty"`
ContentLength *int64 `xml:"Content-Length,omitempty"`
ContentMD5 *string `xml:"Content-MD5,omitempty"`
ContentType *string `xml:"Content-Type,omitempty"`
CopyCompletionTime *string `xml:"CopyCompletionTime,omitempty"`
CopyId *string `xml:"CopyId,omitempty"`
CopyStatus *string `xml:"CopyStatus,omitempty"`
CopySource *string `xml:"CopySource,omitempty"`
CopyProgress *string `xml:"CopyProgress,omitempty"`
CopyStatusDescription *string `xml:"CopyStatusDescription,omitempty"`
CreationTime *string `xml:"CreationTime,omitempty"`
ETag *string `xml:"Etag,omitempty"`
DeletedTime *string `xml:"DeletedTime,omitempty"`
IncrementalCopy *bool `xml:"IncrementalCopy,omitempty"`
LastModified *string `xml:"Last-Modified,omitempty"`
LeaseDuration *string `xml:"LeaseDuration,omitempty"`
LeaseState *string `xml:"LeaseState,omitempty"`
LeaseStatus *string `xml:"LeaseStatus,omitempty"`
RemainingRetentionDays *string `xml:"RemainingRetentionDays,omitempty"`
ServerEncrypted *bool `xml:"ServerEncrypted,omitempty"`
}
type BlobPrefix struct {
Name string `xml:"Name"`
}
// ListBlobs lists the blobs matching the specified query within the specified Container
func (client Client) ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`containerName` cannot be an empty string.")
}
if input.MaxResults != nil && (*input.MaxResults <= 0 || *input.MaxResults > 5000) {
return result, validation.NewError("containers.Client", "ListBlobs", "`input.MaxResults` can either be nil or between 0 and 5000.")
}
req, err := client.ListBlobsPreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", nil, "Failure preparing request")
return
}
resp, err := client.ListBlobsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure sending request")
return
}
result, err = client.ListBlobsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure responding to request")
return
}
return
}
// ListBlobsPreparer prepares the ListBlobs request.
func (client Client) ListBlobsPreparer(ctx context.Context, accountName, containerName string, input ListBlobsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "list"),
"restype": autorest.Encode("query", "container"),
}
if input.Delimiter != nil {
queryParameters["delimiter"] = autorest.Encode("query", *input.Delimiter)
}
if input.Include != nil {
vals := make([]string, 0)
for _, v := range *input.Include {
vals = append(vals, string(v))
}
include := strings.Join(vals, ",")
queryParameters["include"] = autorest.Encode("query", include)
}
if input.Marker != nil {
queryParameters["marker"] = autorest.Encode("query", *input.Marker)
}
if input.MaxResults != nil {
queryParameters["maxresults"] = autorest.Encode("query", *input.MaxResults)
}
if input.Prefix != nil {
queryParameters["prefix"] = autorest.Encode("query", *input.Prefix)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListBlobsSender sends the ListBlobs request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListBlobsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListBlobsResponder handles the response to the ListBlobs request. The method always
// closes the http.Response Body.
func (client Client) ListBlobsResponder(resp *http.Response) (result ListBlobsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/models.go 0000664 0000000 0000000 00000003464 14232154237 0023017 0 ustar 00root root 0000000 0000000 package containers
import "github.com/Azure/go-autorest/autorest"
type AccessLevel string
var (
// Blob specifies public read access for blobs.
// Blob data within this container can be read via anonymous request,
// but container data is not available.
// Clients cannot enumerate blobs within the container via anonymous request.
Blob AccessLevel = "blob"
// Container specifies full public read access for container and blob data.
// Clients can enumerate blobs within the container via anonymous request,
// but cannot enumerate containers within the storage account.
Container AccessLevel = "container"
// Private specifies that container data is private to the account owner
Private AccessLevel = ""
)
type ContainerProperties struct {
autorest.Response
AccessLevel AccessLevel
LeaseStatus LeaseStatus
LeaseState LeaseState
LeaseDuration *LeaseDuration
MetaData map[string]string
HasImmutabilityPolicy bool
HasLegalHold bool
}
type Dataset string
var (
Copy Dataset = "copy"
Deleted Dataset = "deleted"
MetaData Dataset = "metadata"
Snapshots Dataset = "snapshots"
UncommittedBlobs Dataset = "uncommittedblobs"
)
type ErrorResponse struct {
Code *string `xml:"Code"`
Message *string `xml:"Message"`
}
type LeaseDuration string
var (
// If this lease is for a Fixed Duration
Fixed LeaseDuration = "fixed"
// If this lease is for an Indefinite Duration
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
giovanni-0.20.0/storage/2018-03-28/blob/containers/resource_id.go 0000664 0000000 0000000 00000002341 14232154237 0024030 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Container
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, containerName)
}
type ResourceID struct {
AccountName string
ContainerName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Container Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
containerName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/resource_id_test.go 0000664 0000000 0000000 00000003765 14232154237 0025102 0 ustar 00root root 0000000 0000000 package containers
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected the container name to be `container1` but got %q", actual.ContainerName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/set_acl.go 0000664 0000000 0000000 00000007651 14232154237 0023150 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetAccessControl sets the Access Control for a Container without a Lease ID
func (client Client) SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error) {
return client.SetAccessControlWithLeaseID(ctx, accountName, containerName, "", level)
}
// SetAccessControlWithLeaseID sets the Access Control for a Container using the specified Lease ID
func (client Client) SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`containerName` cannot be an empty string.")
}
req, err := client.SetAccessControlWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, level)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure responding to request")
return
}
return
}
// SetAccessControlWithLeaseIDPreparer prepares the SetAccessControlWithLeaseID request.
func (client Client) SetAccessControlWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "acl"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, level)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlWithLeaseIDSender sends the SetAccessControlWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlWithLeaseIDResponder handles the response to the SetAccessControlWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/set_metadata.go 0000664 0000000 0000000 00000010137 14232154237 0024162 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the specified MetaData on the Container without a Lease ID
func (client Client) SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error) {
return client.SetMetaDataWithLeaseID(ctx, accountName, containerName, "", metaData)
}
// SetMetaDataWithLeaseID sets the specified MetaData on the Container using the specified Lease ID
func (client Client) SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("containers.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataWithLeaseIDPreparer prepares the SetMetaDataWithLeaseID request.
func (client Client) SetMetaDataWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataWithLeaseIDSender sends the SetMetaDataWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataWithLeaseIDResponder handles the response to the SetMetaDataWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/blob/containers/version.go 0000664 0000000 0000000 00000000470 14232154237 0023213 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/ 0000775 0000000 0000000 00000000000 14232154237 0020736 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/ 0000775 0000000 0000000 00000000000 14232154237 0023305 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/README.md 0000664 0000000 0000000 00000004413 14232154237 0024566 0 ustar 00root root 0000000 0000000 ## Data Lake Storage Gen2 File Systems SDK for API version 2018-03-28
This package allows you to interact with the Data Lake Storage Gen2 File Systems API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
### Example Usage
```go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/go-azure-helpers/authentication"
"github.com/hashicorp/go-azure-helpers/sender"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/datalakestore/filesystems"
)
func Example() error {
accountName := "storageaccount1"
fileSystemName := "filesystem1"
builder := &authentication.Builder{
SubscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"),
ClientID: os.Getenv("ARM_CLIENT_ID"),
ClientSecret: os.Getenv("ARM_CLIENT_SECRET"),
TenantID: os.Getenv("ARM_TENANT_ID"),
Environment: os.Getenv("ARM_ENVIRONMENT"),
// Feature Toggles
SupportsClientSecretAuth: true,
}
c, err := builder.Build()
if err != nil {
return fmt.Errorf("Error building AzureRM Client: %s", err)
}
env, err := authentication.DetermineEnvironment(c.Environment)
if err != nil {
return err
}
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, c.TenantID)
if err != nil {
return err
}
// OAuthConfigForTenant returns a pointer, which can be nil.
if oauthConfig == nil {
return fmt.Errorf("Unable to configure OAuthConfig for tenant %s", c.TenantID)
}
sender := sender.BuildSender("AzureRM")
ctx := context.Background()
storageAuth, err := config.GetAuthorizationToken(sender, oauthConfig, "https://storage.azure.com/")
if err != nil {
return fmt.Errorf("Error retrieving Authorization Token")
}
fileSystemsClient := filesystems.NewWithEnvironment(env)
fileSystemsClient.Client.Authorizer = storageAuth
input := filesystems.CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
return fmt.Errorf("Error creating: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/client.go 0000664 0000000 0000000 00000001216 14232154237 0025112 0 ustar 00root root 0000000 0000000 package filesystems
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Data Lake Storage FileSystem
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Data Lake Storage FileSystem client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Data Lake Storage FileSystem client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/create.go 0000664 0000000 0000000 00000006425 14232154237 0025106 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type CreateInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
}
// Create creates a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Create(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`fileSystemName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure responding to request")
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/create_test.go 0000664 0000000 0000000 00000003202 14232154237 0026133 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCreateHasNoTagsByDefault(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 0 {
t.Fatalf("Expected 0 properties by default but got %d", len(props.Properties))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/delete.go 0000664 0000000 0000000 00000005514 14232154237 0025103 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Delete(ctx context.Context, accountName string, fileSystemName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`fileSystemName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure responding to request")
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/helpers.go 0000664 0000000 0000000 00000002041 14232154237 0025273 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"strings"
)
func buildProperties(input map[string]string) string {
// properties has to be a comma-separated key-value pair
properties := make([]string, 0)
for k, v := range input {
properties = append(properties, fmt.Sprintf("%s=%s", k, v))
}
return strings.Join(properties, ",")
}
func parseProperties(input string) (*map[string]string, error) {
properties := make(map[string]string)
if input == "" {
return &properties, nil
}
// properties is a comma-separated list of key-value pairs
splitProperties := strings.Split(input, ",")
for _, propertyRaw := range splitProperties {
// because these are base64-encoded they're likely to end in at least one =
// as such we can't string split on that -_-
position := strings.Index(propertyRaw, "=")
if position < 0 {
return nil, fmt.Errorf("Expected there to be an equals in the key value pair: %q", propertyRaw)
}
key := propertyRaw[0:position]
value := propertyRaw[position+1:]
properties[key] = value
}
return &properties, nil
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/helpers_test.go 0000664 0000000 0000000 00000002724 14232154237 0026342 0 ustar 00root root 0000000 0000000 package filesystems
import (
"reflect"
"testing"
)
func TestParseProperties(t *testing.T) {
testData := []struct {
name string
input string
expected map[string]string
expectError bool
}{
{
name: "no items",
input: "",
expected: map[string]string{},
expectError: false,
},
{
name: "invalid item",
input: "hello",
expectError: true,
},
{
name: "single item",
input: "hello=world",
expected: map[string]string{
"hello": "world",
},
},
{
name: "single-item-base64",
input: "hello=aGVsbG8=",
expected: map[string]string{
"hello": "aGVsbG8=",
},
expectError: false,
},
{
name: "single-item-base64-multipleequals",
input: "hello=d29uZGVybGFuZA==",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
},
expectError: false,
},
{
name: "multiple-items-base64",
input: "hello=d29uZGVybGFuZA==,private=ZXll",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
expectError: false,
},
}
for _, testCase := range testData {
t.Logf("[DEBUG] Test %q", testCase.name)
actual, err := parseProperties(testCase.input)
if err != nil {
if testCase.expectError {
continue
}
t.Fatalf("[DEBUG] Didn't expect an error but got %s", err)
}
if !reflect.DeepEqual(testCase.expected, *actual) {
t.Fatalf("Expected %+v but got %+v", testCase.expected, *actual)
}
}
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/lifecycle_test.go 0000664 0000000 0000000 00000005302 14232154237 0026632 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{
"hello": "aGVsbG8=",
},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 1 {
t.Fatalf("Expected 1 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "aGVsbG8=" {
t.Fatalf("Expected `hello` to be `aGVsbG8=` but got %q", props.Properties["hello"])
}
t.Logf("[DEBUG] Updating the properties..")
setInput := SetPropertiesInput{
Properties: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
}
if _, err := fileSystemsClient.SetProperties(ctx, accountName, fileSystemName, setInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Properties..")
props, err = fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 2 {
t.Fatalf("Expected 2 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "d29uZGVybGFuZA==" {
t.Fatalf("Expected `hello` to be `d29uZGVybGFuZA==` but got %q", props.Properties["hello"])
}
if props.Properties["private"] != "ZXll" {
t.Fatalf("Expected `private` to be `ZXll` but got %q", props.Properties["private"])
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/properties_get.go 0000664 0000000 0000000 00000007435 14232154237 0026700 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPropertiesResponse struct {
autorest.Response
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Is Hierarchical Namespace Enabled?
NamespaceEnabled bool
}
// GetProperties gets the properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) GetProperties(ctx context.Context, accountName string, fileSystemName string) (result GetPropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure responding to request")
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResponse, err error) {
if resp != nil && resp.Header != nil {
propertiesRaw := resp.Header.Get("x-ms-properties")
var properties *map[string]string
properties, err = parseProperties(propertiesRaw)
if err != nil {
return
}
result.Properties = *properties
result.NamespaceEnabled = strings.EqualFold(resp.Header.Get("x-ms-namespace-enabled"), "tru")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/properties_set.go 0000664 0000000 0000000 00000007773 14232154237 0026721 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has been modified since the specified date and time.
IfModifiedSince *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has not been modified since the specified date and time.
IfUnmodifiedSince *string
}
// SetProperties sets the Properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) SetProperties(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure responding to request")
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
preparer := autorest.CreatePreparer(
autorest.AsPatch(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/resource_id.go 0000664 0000000 0000000 00000002417 14232154237 0026143 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Data Lake Storage FileSystem
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
type ResourceID struct {
AccountName string
DirectoryName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Data Lake Storage FileSystem API's
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.dfs.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
directoryName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/resource_id_test.go 0000664 0000000 0000000 00000003756 14232154237 0027211 0 ustar 00root root 0000000 0000000 package filesystems
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected the directory name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/datalakestore/filesystems/version.go 0000664 0000000 0000000 00000000471 14232154237 0025323 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/file/ 0000775 0000000 0000000 00000000000 14232154237 0017032 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/file/directories/ 0000775 0000000 0000000 00000000000 14232154237 0021346 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/file/directories/README.md 0000664 0000000 0000000 00000002135 14232154237 0022626 0 ustar 00root root 0000000 0000000 ## File Storage Directories SDK for API version 2018-03-28
This package allows you to interact with the Directories File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/directories"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
directoriesClient := directories.New()
directoriesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := directoriesClient.Create(ctx, accountName, shareName, directoryName, metadata); err != nil {
return fmt.Errorf("Error creating Directory: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/file/directories/client.go 0000664 0000000 0000000 00000001132 14232154237 0023150 0 ustar 00root root 0000000 0000000 package directories
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/file/directories/create.go 0000664 0000000 0000000 00000007054 14232154237 0023146 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates a new directory under the specified share or parent directory.
func (client Client) Create(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Create", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Create", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/directories/delete.go 0000664 0000000 0000000 00000006343 14232154237 0023145 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete removes the specified empty directory
// Note that the directory must be empty before it can be deleted.
func (client Client) Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Delete", "`path` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/directories/get.go 0000664 0000000 0000000 00000007432 14232154237 0022462 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
// A set of name-value pairs that contain metadata for the directory.
MetaData map[string]string
// The value of this header is set to true if the directory metadata is completely
// encrypted using the specified algorithm. Otherwise, the value is set to false.
DirectoryMetaDataEncrypted bool
}
// Get returns all system properties for the specified directory,
// and can also be used to check the existence of a directory.
func (client Client) Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Get", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Get", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Get", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Get", "`path` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
result.DirectoryMetaDataEncrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/directories/lifecycle_test.go 0000664 0000000 0000000 00000007306 14232154237 0024701 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestDirectoriesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
directoriesClient := NewWithEnvironment(client.Environment)
directoriesClient.Client = client.PrepareWithAuthorizer(directoriesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, true)
metaData := map[string]string{
"hello": "world",
}
log.Printf("[DEBUG] Creating Top Level..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello", metaData); err != nil {
t.Fatalf("Error creating Top Level Directory: %s", err)
}
log.Printf("[DEBUG] Creating Inner..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello/there", metaData); err != nil {
t.Fatalf("Error creating Inner Directory: %s", err)
}
log.Printf("[DEBUG] Retrieving share")
innerDir, err := directoriesClient.Get(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving Inner Directory: %s", err)
}
if innerDir.DirectoryMetaDataEncrypted != true {
t.Fatalf("Expected MetaData to be encrypted but got: %t", innerDir.DirectoryMetaDataEncrypted)
}
if len(innerDir.MetaData) != 1 {
t.Fatalf("Expected MetaData to contain 1 item but got %d", len(innerDir.MetaData))
}
if innerDir.MetaData["hello"] != "world" {
t.Fatalf("Expected MetaData `hello` to be `world`: %s", innerDir.MetaData["hello"])
}
log.Printf("[DEBUG] Setting MetaData")
updatedMetaData := map[string]string{
"panda": "pops",
}
if _, err := directoriesClient.SetMetaData(ctx, accountName, shareName, "hello/there", updatedMetaData); err != nil {
t.Fatalf("Error updating MetaData: %s", err)
}
log.Printf("[DEBUG] Retrieving MetaData")
retrievedMetaData, err := directoriesClient.GetMetaData(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving the updated metadata: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected the updated metadata to have 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["panda"] != "pops" {
t.Fatalf("Expected the metadata `panda` to be `pops` but got %q", retrievedMetaData.MetaData["panda"])
}
t.Logf("[DEBUG] Deleting Inner..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello/there"); err != nil {
t.Fatalf("Error deleting Inner Directory: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello"); err != nil {
t.Fatalf("Error deleting Top Level Directory: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/file/directories/metadata_get.go 0000664 0000000 0000000 00000007127 14232154237 0024323 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns all user-defined metadata for the specified directory
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`path` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/directories/metadata_set.go 0000664 0000000 0000000 00000007273 14232154237 0024341 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates user defined metadata for the specified directory
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/directories/resource_id.go 0000664 0000000 0000000 00000003113 14232154237 0024176 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Directory
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, shareName, directoryName)
}
type ResourceID struct {
AccountName string
DirectoryName string
ShareName string
}
// ParseResourceID parses the Resource ID into an Object
// which can be used to interact with the Directory within the File Share
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar/Folder
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/file/directories/resource_id_test.go 0000664 0000000 0000000 00000004246 14232154237 0025245 0 ustar 00root root 0000000 0000000 package directories
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/file/directories/version.go 0000664 0000000 0000000 00000000471 14232154237 0023364 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/file/files/ 0000775 0000000 0000000 00000000000 14232154237 0020134 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/file/files/README.md 0000664 0000000 0000000 00000002064 14232154237 0021415 0 ustar 00root root 0000000 0000000 ## File Storage Files SDK for API version 2018-03-28
This package allows you to interact with the Files File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/files"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
fileName := "example.txt"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
filesClient := files.New()
filesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := files.CreateInput{}
if _, err := filesClient.Create(ctx, accountName, shareName, directoryName, fileName, input); err != nil {
return fmt.Errorf("Error creating File: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/file/files/client.go 0000664 0000000 0000000 00000001124 14232154237 0021737 0 ustar 00root root 0000000 0000000 package files
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/file/files/copy.go 0000664 0000000 0000000 00000011216 14232154237 0021436 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the URL of the source file or blob, up to 2 KB in length.
//
// To copy a file to another file within the same storage account, you may use Shared Key to authenticate
// the source file. If you are copying a file from another storage account, or if you are copying a blob from
// the same storage account or another storage account, then you must authenticate the source file or blob using a
// shared access signature. If the source is a public blob, no authentication is required to perform the copy
// operation. A file in a share snapshot can also be specified as a copy source.
CopySource string
MetaData map[string]string
}
type CopyResult struct {
autorest.Response
// The CopyID, which can be passed to AbortCopy to abort the copy.
CopyID string
// Either `success` or `pending`
CopySuccess string
}
// Copy copies a blob or file to a destination file within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Copy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Copy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Copy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Copy", "`fileName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("files.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Copy", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CopyPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopySuccess = resp.Header.Get("x-ms-copy-status")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/copy_abort.go 0000664 0000000 0000000 00000007157 14232154237 0022636 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// AbortCopy aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata
func (client Client) AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`fileName` cannot be an empty string.")
}
if copyID == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`copyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, shareName, path, fileName, copyID)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, shareName, path, fileName, copyID string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", copyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/copy_wait.go 0000664 0000000 0000000 00000002414 14232154237 0022462 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
)
type CopyAndWaitResult struct {
autorest.Response
CopyID string
}
const DefaultCopyPollDuration = 15 * time.Second
// CopyAndWait is a convenience method which doesn't exist in the API, which copies the file and then waits for the copy to complete
func (client Client) CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error) {
copy, e := client.Copy(ctx, accountName, shareName, path, fileName, input)
if err != nil {
result.Response = copy.Response
err = fmt.Errorf("Error copying: %s", e)
return
}
result.CopyID = copy.CopyID
// since the API doesn't return a LRO, this is a hack which also polls every 10s, but should be sufficient
for true {
props, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if e != nil {
result.Response = copy.Response
err = fmt.Errorf("Error waiting for copy: %s", e)
return
}
switch strings.ToLower(props.CopyStatus) {
case "pending":
time.Sleep(pollDuration)
continue
case "success":
return
default:
err = fmt.Errorf("Unexpected CopyState %q", e)
return
}
}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/copy_wait_test.go 0000664 0000000 0000000 00000011043 14232154237 0023517 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestFilesCopyAndWaitFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
copiedFileName := "ubuntu.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
func TestFilesCopyAndWaitFromBlob(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
originalFileName := "ubuntu.iso"
copiedFileName := "ubuntu-copied.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting the original file..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", originalFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Now copying that blob..")
duplicateInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetFileEndpoint(filesClient.BaseURI, accountName), shareName, originalFileName),
}
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, duplicateInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copying duplicate: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
giovanni-0.20.0/storage/2018-03-28/file/files/create.go 0000664 0000000 0000000 00000011330 14232154237 0021724 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// This header specifies the maximum size for the file, up to 1 TiB.
ContentLength int64
// The MIME content type of the file
// If not specified, the default type is application/octet-stream.
ContentType *string
// Specifies which content encodings have been applied to the file.
// This value is returned to the client when the Get File operation is performed
// on the file resource and can be used to decode file content.
ContentEncoding *string
// Specifies the natural languages used by this resource.
ContentLanguage *string
// The File service stores this value but does not use or modify it.
CacheControl *string
// Sets the file's MD5 hash.
ContentMD5 *string
// Sets the file’s Content-Disposition header.
ContentDisposition *string
MetaData map[string]string
}
// Create creates a new file or replaces a file.
func (client Client) Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Create", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Create", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Create", "`input.MetaData` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-content-length": input.ContentLength,
"x-ms-type": "file",
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/delete.go 0000664 0000000 0000000 00000006206 14232154237 0021731 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete immediately deletes the file from the File Share.
func (client Client) Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Delete", "`fileName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/lifecycle_test.go 0000664 0000000 0000000 00000011627 14232154237 0023470 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestFilesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
fileName := "bled5.png"
contentEncoding := "application/vnd+panda"
t.Logf("[DEBUG] Creating Top Level File..")
createInput := CreateInput{
ContentLength: 1024,
ContentEncoding: &contentEncoding,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Top-Level File..")
file, err := filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 1024 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != contentEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", contentEncoding, file.ContentEncoding)
}
updatedSize := int64(2048)
updatedEncoding := "application/vnd+pandas2"
updatedInput := SetPropertiesInput{
ContentEncoding: &updatedEncoding,
ContentLength: &updatedSize,
}
if _, err := filesClient.SetProperties(ctx, accountName, shareName, "", fileName, updatedInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Properties for the Top-Level File..")
file, err = filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 2048 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != updatedEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", updatedEncoding, file.ContentEncoding)
}
t.Logf("[DEBUG] Setting MetaData..")
metaData := map[string]string{
"hello": "there",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Retrieving MetaData..")
retrievedMetaData, err := filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
t.Logf("[DEBUG] Re-Setting MetaData..")
metaData = map[string]string{
"hello": "there",
"second": "thing",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving MetaData..")
retrievedMetaData, err = filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 2 {
t.Fatalf("Expected 2 items but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
if retrievedMetaData.MetaData["second"] != "thing" {
t.Fatalf("Expected `second` to be `thing` but got %q", retrievedMetaData.MetaData["second"])
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/file/files/metadata_get.go 0000664 0000000 0000000 00000007263 14232154237 0023112 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData for the specified File.
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`fileName` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
//metadata.ByParsingFromHeaders(&result.MetaData),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/metadata_set.go 0000664 0000000 0000000 00000007347 14232154237 0023131 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates the specified File to have the specified MetaData.
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("files.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, fileName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/properties_get.go 0000664 0000000 0000000 00000012146 14232154237 0023522 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
CacheControl string
ContentDisposition string
ContentEncoding string
ContentLanguage string
ContentLength *int64
ContentMD5 string
ContentType string
CopyID string
CopyStatus string
CopySource string
CopyProgress string
CopyStatusDescription string
CopyCompletionTime string
Encrypted bool
MetaData map[string]string
}
// GetProperties returns the Properties for the specified file
func (client Client) GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("x-ms-content-md5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = resp.Header.Get("x-ms-copy-status")
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.Encrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
contentLengthRaw := resp.Header.Get("Content-Length")
if contentLengthRaw != "" {
contentLength, err := strconv.Atoi(contentLengthRaw)
if err != nil {
return result, fmt.Errorf("Error parsing %q for Content-Length as an integer: %s", contentLengthRaw, err)
}
contentLengthI64 := int64(contentLength)
result.ContentLength = &contentLengthI64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/properties_set.go 0000664 0000000 0000000 00000013714 14232154237 0023540 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
// Resizes a file to the specified size.
// If the specified byte value is less than the current size of the file,
// then all ranges above the specified byte value are cleared.
ContentLength *int64
// Modifies the cache control string for the file.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentControl *string
// Sets the file’s Content-Disposition header.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentDisposition *string
// Sets the file's content encoding.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentEncoding *string
// Sets the file's content language.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentLanguage *string
// Sets the file's MD5 hash.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentMD5 *string
// Sets the file's content type.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentType *string
}
// SetProperties sets the specified properties on the specified File
func (client Client) SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-type": "file",
}
if input.ContentControl != nil {
headers["x-ms-cache-control"] = *input.ContentControl
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-content-language"] = *input.ContentLanguage
}
if input.ContentLength != nil {
headers["x-ms-content-length"] = *input.ContentLength
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/range_clear.go 0000664 0000000 0000000 00000007740 14232154237 0022735 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ClearByteRangeInput struct {
StartBytes int64
EndBytes int64
}
// ClearByteRange clears the specified Byte Range from within the specified File
func (client Client) ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.EndBytes` must be greater than 0.")
}
req, err := client.ClearByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", nil, "Failure preparing request")
return
}
resp, err := client.ClearByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure sending request")
return
}
result, err = client.ClearByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure responding to request")
return
}
return
}
// ClearByteRangePreparer prepares the ClearByteRange request.
func (client Client) ClearByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes),
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ClearByteRangeSender sends the ClearByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ClearByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ClearByteRangeResponder handles the response to the ClearByteRange request. The method always
// closes the http.Response Body.
func (client Client) ClearByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/range_get.go 0000664 0000000 0000000 00000010430 14232154237 0022414 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetByteRangeInput struct {
StartBytes int64
EndBytes int64
}
type GetByteRangeResult struct {
autorest.Response
Contents []byte
}
// GetByteRange returns the specified Byte Range from the specified File.
func (client Client) GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at most 4MB.")
}
req, err := client.GetByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", nil, "Failure preparing request")
return
}
resp, err := client.GetByteRangeSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure sending request")
return
}
result, err = client.GetByteRangeResponder(resp, expectedBytes)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure responding to request")
return
}
return
}
// GetByteRangePreparer prepares the GetByteRange request.
func (client Client) GetByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetByteRangeSender sends the GetByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetByteRangeResponder handles the response to the GetByteRange request. The method always
// closes the http.Response Body.
func (client Client) GetByteRangeResponder(resp *http.Response, length int64) (result GetByteRangeResult, err error) {
result.Contents = make([]byte, length)
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/range_get_file.go 0000664 0000000 0000000 00000006055 14232154237 0023423 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"log"
"math"
"runtime"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// GetFile is a helper method to download a file by chunking it automatically
func (client Client) GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error) {
// first look up the file and check out how many bytes it is
file, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if err != nil {
result = file.Response
err = e
return
}
if file.ContentLength == nil {
err = fmt.Errorf("Content-Length was nil!")
return
}
length := int64(*file.ContentLength)
chunkSize := int64(4 * 1024 * 1024) // 4MB
if chunkSize > length {
chunkSize = length
}
// then split that up into chunks and retrieve it retrieve it into the 'results' set
chunks := int(math.Ceil(float64(length) / float64(chunkSize)))
workerCount := parallelism * runtime.NumCPU()
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
results := make([]*downloadFileChunkResult, chunks)
errors := make(chan error, chunkSize)
for i := 0; i < chunks; i++ {
go func(i int) {
log.Printf("[DEBUG] Downloading Chunk %d of %d", i+1, chunks)
dfci := downloadFileChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: length,
}
result, err := client.downloadFileChunk(ctx, accountName, shareName, path, fileName, dfci)
if err != nil {
errors <- err
waitGroup.Done()
return
}
// if there's no error, we should have bytes, so this is safe
results[i] = result
waitGroup.Done()
}(i)
}
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
err = fmt.Errorf("Error downloading file: %s", <-errors)
return
}
// then finally put it all together, in order and return it
output := make([]byte, length)
for _, v := range results {
copy(output[v.startBytes:v.endBytes], v.bytes)
}
outputBytes = output
return
}
type downloadFileChunkInput struct {
thisChunk int
chunkSize int64
fileSize int64
}
type downloadFileChunkResult struct {
startBytes int64
endBytes int64
bytes []byte
}
func (client Client) downloadFileChunk(ctx context.Context, accountName, shareName, path, fileName string, input downloadFileChunkInput) (*downloadFileChunkResult, error) {
startBytes := input.chunkSize * int64(input.thisChunk)
endBytes := startBytes + input.chunkSize
// the last chunk may exceed the size of the file
remaining := input.fileSize - startBytes
if input.chunkSize > remaining {
endBytes = startBytes + remaining
}
getInput := GetByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
}
result, err := client.GetByteRange(ctx, accountName, shareName, path, fileName, getInput)
if err != nil {
return nil, fmt.Errorf("Error putting bytes: %s", err)
}
output := downloadFileChunkResult{
startBytes: startBytes,
endBytes: endBytes,
bytes: result.Contents,
}
return &output, nil
}
giovanni-0.20.0/storage/2018-03-28/file/files/range_get_file_test.go 0000664 0000000 0000000 00000007063 14232154237 0024462 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestGetSmallFile(t *testing.T) {
// the purpose of this test is to verify that the small, single-chunked file gets downloaded correctly
testGetFile(t, "small-file.png", "image/png")
}
func TestGetLargeFile(t *testing.T) {
// the purpose of this test is to verify that the large, multi-chunked file gets downloaded correctly
testGetFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testGetFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Downloading file..")
_, downloadedBytes, err := filesClient.GetFile(ctx, accountName, shareName, "", fileName, 4)
if err != nil {
t.Fatalf("Error downloading file: %s", err)
}
t.Logf("[DEBUG] Asserting the files are the same size..")
expectedBytes := make([]byte, info.Size())
file.Read(expectedBytes)
if len(expectedBytes) != len(downloadedBytes) {
t.Fatalf("Expected %d bytes but got %d", len(expectedBytes), len(downloadedBytes))
}
t.Logf("[DEBUG] Asserting the files are the same content-wise..")
// overkill, but it's this or shasum-ing
for i := int64(0); i < info.Size(); i++ {
if expectedBytes[i] != downloadedBytes[i] {
t.Fatalf("Expected byte %d to be %q but got %q", i, expectedBytes[i], downloadedBytes[i])
}
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/file/files/range_put.go 0000664 0000000 0000000 00000011226 14232154237 0022451 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutByteRangeInput struct {
StartBytes int64
EndBytes int64
// Content is the File Contents for the specified range
// which can be at most 4MB
Content []byte
}
// PutByteRange puts the specified Byte Range in the specified File.
func (client Client) PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
actualBytes := len(input.Content)
if expectedBytes != int64(actualBytes) {
return result, validation.NewError("files.Client", "PutByteRange", fmt.Sprintf("The specified byte-range (%d) didn't match the content size (%d).", expectedBytes, actualBytes))
}
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at most 4MB.")
}
req, err := client.PutByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", nil, "Failure preparing request")
return
}
resp, err := client.PutByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure sending request")
return
}
result, err = client.PutByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure responding to request")
return
}
return
}
// PutByteRangePreparer prepares the PutByteRange request.
func (client Client) PutByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
"Content-Length": int(len(input.Content)),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutByteRangeSender sends the PutByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutByteRangeResponder handles the response to the PutByteRange request. The method always
// closes the http.Response Body.
func (client Client) PutByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/range_put_file.go 0000664 0000000 0000000 00000005070 14232154237 0023450 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"io"
"log"
"math"
"os"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// PutFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
chunkSize := 4 * 1024 * 1024 // 4MB
if chunkSize > int(fileSize) {
chunkSize = int(fileSize)
}
chunks := int(math.Ceil(float64(fileSize) / float64(chunkSize*1.0)))
workerCount := parallelism
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
jobs := make(chan int, workerCount)
errors := make(chan error, chunkSize)
for i := 0; i < workerCount; i++ {
go func() {
for i := range jobs {
log.Printf("[DEBUG] Chunk %d of %d", i+1, chunks)
uci := uploadChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: fileSize,
}
_, err := client.uploadChunk(ctx, accountName, shareName, path, fileName, uci, file)
if err != nil {
errors <- err
}
}
waitGroup.Done()
}()
}
for i := 0; i < chunks; i++ {
jobs <- i
}
close(jobs)
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
return fmt.Errorf("Error uploading file: %s", <-errors)
}
return nil
}
type uploadChunkInput struct {
thisChunk int
chunkSize int
fileSize int64
}
func (client Client) uploadChunk(ctx context.Context, accountName, shareName, path, fileName string, input uploadChunkInput, file *os.File) (result autorest.Response, err error) {
startBytes := int64(input.chunkSize * input.thisChunk)
endBytes := startBytes + int64(input.chunkSize)
// the last size may exceed the size of the file
remaining := input.fileSize - startBytes
if int64(input.chunkSize) > remaining {
endBytes = startBytes + remaining
}
bytesToRead := int(endBytes) - int(startBytes)
bytes := make([]byte, bytesToRead)
_, err = file.ReadAt(bytes, startBytes)
if err != nil {
if err != io.EOF {
return result, fmt.Errorf("Error reading bytes: %s", err)
}
}
putBytesInput := PutByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
Content: bytes,
}
result, err = client.PutByteRange(ctx, accountName, shareName, path, fileName, putBytesInput)
if err != nil {
return result, fmt.Errorf("Error putting bytes: %s", err)
}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/range_put_file_test.go 0000664 0000000 0000000 00000005413 14232154237 0024510 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPutSmallFile(t *testing.T) {
// the purpose of this test is to ensure that a small file (< 4MB) is a single chunk
testPutFile(t, "small-file.png", "image/png")
}
func TestPutLargeFile(t *testing.T) {
// the purpose of this test is to ensure that large files (> 4MB) are chunked
testPutFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testPutFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/file/files/ranges_list.go 0000664 0000000 0000000 00000007277 14232154237 0023012 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListRangesResult struct {
autorest.Response
Ranges []Range `xml:"Range"`
}
type Range struct {
Start string `xml:"Start"`
End string `xml:"End"`
}
// ListRanges returns the list of valid ranges for the specified File.
func (client Client) ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("files.Client", "ListRanges", "`path` cannot be an empty string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`fileName` cannot be an empty string.")
}
req, err := client.ListRangesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", nil, "Failure preparing request")
return
}
resp, err := client.ListRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure sending request")
return
}
result, err = client.ListRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure responding to request")
return
}
return
}
// ListRangesPreparer prepares the ListRanges request.
func (client Client) ListRangesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "rangelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListRangesSender sends the ListRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListRangesResponder handles the response to the ListRanges request. The method always
// closes the http.Response Body.
func (client Client) ListRangesResponder(resp *http.Response) (result ListRangesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/files/resource_id.go 0000664 0000000 0000000 00000003654 14232154237 0022776 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName, filePath string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s/%s", domain, shareName, directoryName, filePath)
}
type ResourceID struct {
AccountName string
DirectoryName string
FileName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with Files within a Storage Share.
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
fileName := segments[len(segments)-1]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
directoryName = strings.TrimSuffix(directoryName, fileName)
directoryName = strings.TrimSuffix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
FileName: fileName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/file/files/resource_id_test.go 0000664 0000000 0000000 00000007430 14232154237 0024031 0 ustar 00root root 0000000 0000000 package files
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1", "file1.txt")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/directory2/file1.txt",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1/directory2" {
t.Fatalf("Expected Directory Name to be `directory1/directory2` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/file/files/version.go 0000664 0000000 0000000 00000000463 14232154237 0022153 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/file/shares/ 0000775 0000000 0000000 00000000000 14232154237 0020317 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/file/shares/README.md 0000664 0000000 0000000 00000001777 14232154237 0021612 0 ustar 00root root 0000000 0000000 ## File Storage Shares SDK for API version 2018-03-28
This package allows you to interact with the Shares File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/file/shares"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
sharesClient := shares.New()
sharesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := shares.CreateInput{
QuotaInGB: 2,
}
if _, err := sharesClient.Create(ctx, accountName, shareName, input); err != nil {
return fmt.Errorf("Error creating Share: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/file/shares/acl_get.go 0000664 0000000 0000000 00000006213 14232154237 0022246 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL get the Access Control List for the specified Storage Share
func (client Client) GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.GetACLPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/acl_set.go 0000664 0000000 0000000 00000006415 14232154237 0022266 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"encoding/xml"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List on the specified Storage Share
func (client Client) SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.SetACLPreparer(ctx, accountName, shareName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/client.go 0000664 0000000 0000000 00000001125 14232154237 0022123 0 ustar 00root root 0000000 0000000 package shares
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/file/shares/create.go 0000664 0000000 0000000 00000007365 14232154237 0022124 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies the maximum size of the share, in gigabytes.
// Must be greater than 0, and less than or equal to 5TB (5120).
QuotaInGB int
MetaData map[string]string
}
// Create creates the specified Storage Share within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Create", "`shareName` must be a lower-cased string.")
}
if input.QuotaInGB <= 0 || input.QuotaInGB > 102400 {
return result, validation.NewError("shares.Client", "Create", "`input.QuotaInGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": input.QuotaInGB,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/delete.go 0000664 0000000 0000000 00000006120 14232154237 0022107 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Storage Share from within a Storage Account
func (client Client) Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Delete", "`shareName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, deleteSnapshots)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if deleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/lifecycle_test.go 0000664 0000000 0000000 00000020771 14232154237 0023653 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestSharesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 5)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 5 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
func TestSharesLifecycleLargeQuota(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResourcesWithSku(ctx, resourceGroup, accountName, storage.KindFileStorage, storage.SkuNamePremiumLRS)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1001,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1001 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 6000)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 6000 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/file/shares/metadata_get.go 0000664 0000000 0000000 00000006525 14232154237 0023275 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData associated with the specified Storage Share
func (client Client) GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/metadata_set.go 0000664 0000000 0000000 00000006703 14232154237 0023307 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the MetaData on the specified Storage Share
func (client Client) SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("shares.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/models.go 0000664 0000000 0000000 00000000416 14232154237 0022132 0 ustar 00root root 0000000 0000000 package shares
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2018-03-28/file/shares/properties_get.go 0000664 0000000 0000000 00000007150 14232154237 0023704 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesResult struct {
autorest.Response
MetaData map[string]string
ShareQuota int
}
// GetProperties returns the properties about the specified Storage Share
func (client Client) GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
quotaRaw := resp.Header.Get("x-ms-share-quota")
if quotaRaw != "" {
quota, e := strconv.Atoi(quotaRaw)
if e != nil {
return result, fmt.Errorf("Error converting %q to an integer: %s", quotaRaw, err)
}
result.ShareQuota = quota
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/properties_set.go 0000664 0000000 0000000 00000006617 14232154237 0023727 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetProperties lets you update the Quota for the specified Storage Share
func (client Client) SetProperties(ctx context.Context, accountName, shareName string, newQuotaGB int) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if newQuotaGB <= 0 || newQuotaGB > 102400 {
return result, validation.NewError("shares.Client", "SetProperties", "`newQuotaGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, newQuotaGB)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName string, quotaGB int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": quotaGB,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/resource_id.go 0000664 0000000 0000000 00000002320 14232154237 0023146 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File Share
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
type ResourceID struct {
AccountName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Storage Shares SDK
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
shareName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/file/shares/resource_id_test.go 0000664 0000000 0000000 00000003671 14232154237 0024217 0 ustar 00root root 0000000 0000000 package shares
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected the share name to be `share1` but got %q", actual.ShareName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/file/shares/snapshot_create.go 0000664 0000000 0000000 00000010266 14232154237 0024035 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateSnapshotInput struct {
MetaData map[string]string
}
type CreateSnapshotResult struct {
autorest.Response
// This header is a DateTime value that uniquely identifies the share snapshot.
// The value of this header may be used in subsequent requests to access the share snapshot.
// This value is opaque.
SnapshotDateTime string
}
// CreateSnapshot creates a read-only snapshot of the share
// A share can support creation of 200 share snapshots. Attempting to create more than 200 share snapshots fails with 409 (Conflict).
// Attempting to create a share snapshot while a previous Snapshot Share operation is in progress fails with 409 (Conflict).
func (client Client) CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "CreateSnapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreateSnapshotPreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.CreateSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure sending request")
return
}
result, err = client.CreateSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure responding to request")
return
}
return
}
// CreateSnapshotPreparer prepares the CreateSnapshot request.
func (client Client) CreateSnapshotPreparer(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSnapshotSender sends the CreateSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateSnapshotResponder handles the response to the CreateSnapshot request. The method always
// closes the http.Response Body.
func (client Client) CreateSnapshotResponder(resp *http.Response) (result CreateSnapshotResult, err error) {
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/snapshot_delete.go 0000664 0000000 0000000 00000006552 14232154237 0024037 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// DeleteSnapshot deletes the specified Snapshot of a Storage Share
func (client Client) DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` must be a lower-cased string.")
}
if shareSnapshot == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareSnapshot` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, shareName, shareSnapshot)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, shareName string, shareSnapshot string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
"sharesnapshot": autorest.Encode("query", shareSnapshot),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/snapshot_get.go 0000664 0000000 0000000 00000007101 14232154237 0023343 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetSnapshotPropertiesResult struct {
autorest.Response
MetaData map[string]string
}
// GetSnapshot gets information about the specified Snapshot of the specified Storage Share
func (client Client) GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` must be a lower-cased string.")
}
if snapshotShare == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`snapshotShare` cannot be an empty string.")
}
req, err := client.GetSnapshotPreparer(ctx, accountName, shareName, snapshotShare)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.GetSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure sending request")
return
}
result, err = client.GetSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPreparer(ctx context.Context, accountName, shareName, snapshotShare string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"snapshot": autorest.Encode("query", snapshotShare),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSnapshotSender sends the GetSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetSnapshotResponder handles the response to the GetSnapshot request. The method always
// closes the http.Response Body.
func (client Client) GetSnapshotResponder(resp *http.Response) (result GetSnapshotPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/stats.go 0000664 0000000 0000000 00000006470 14232154237 0022013 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetStatsResult struct {
autorest.Response
// The approximate size of the data stored on the share.
// Note that this value may not include all recently created or recently resized files.
ShareUsageBytes int64 `xml:"ShareUsageBytes"`
}
// GetStats returns information about the specified Storage Share
func (client Client) GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` must be a lower-cased string.")
}
req, err := client.GetStatsPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", nil, "Failure preparing request")
return
}
resp, err := client.GetStatsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure sending request")
return
}
result, err = client.GetStatsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure responding to request")
return
}
return
}
// GetStatsPreparer prepares the GetStats request.
func (client Client) GetStatsPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "stats"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetStatsSender sends the GetStats request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetStatsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetStatsResponder handles the response to the GetStats request. The method always
// closes the http.Response Body.
func (client Client) GetStatsResponder(resp *http.Response) (result GetStatsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/file/shares/version.go 0000664 0000000 0000000 00000000464 14232154237 0022337 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/queue/ 0000775 0000000 0000000 00000000000 14232154237 0017237 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/queue/messages/ 0000775 0000000 0000000 00000000000 14232154237 0021046 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/queue/messages/README.md 0000664 0000000 0000000 00000002062 14232154237 0022325 0 ustar 00root root 0000000 0000000 ## Queue Storage Messages SDK for API version 2018-03-28
This package allows you to interact with the Messages Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/queue/messages"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
messagesClient := messages.New()
messagesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := messages.PutInput{
Message: "hello",
}
if _, err := messagesClient.Put(ctx, accountName, queueName, input); err != nil {
return fmt.Errorf("Error creating Message: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/queue/messages/client.go 0000664 0000000 0000000 00000001114 14232154237 0022650 0 ustar 00root root 0000000 0000000 package messages
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Messages.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/delete.go 0000664 0000000 0000000 00000006523 14232154237 0022645 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a specific message
func (client Client) Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Delete", "`queueName` must be a lower-cased string.")
}
if messageID == "" {
return result, validation.NewError("messages.Client", "Delete", "`messageID` cannot be an empty string.")
}
if popReceipt == "" {
return result, validation.NewError("messages.Client", "Delete", "`popReceipt` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName, messageID, popReceipt)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, queueName, messageID, popReceipt string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", popReceipt),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/get.go 0000664 0000000 0000000 00000007666 14232154237 0022173 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
// VisibilityTimeout specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
VisibilityTimeout *int
}
// Get retrieves one or more messages from the front of the queue
func (client Client) Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Get", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Get", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Get", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Get", "`numberOfMessages` must be between 1 and 32.")
}
if input.VisibilityTimeout != nil {
t := *input.VisibilityTimeout
maxTime := (time.Hour * 24 * 7).Seconds()
if t < 1 || t < int(maxTime) {
return result, validation.NewError("messages.Client", "Get", "`input.VisibilityTimeout` must be larger than or equal to 1 second, and cannot be larger than 7 days.")
}
}
req, err := client.GetPreparer(ctx, accountName, queueName, numberOfMessages, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("query", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/lifecycle_test.go 0000664 0000000 0000000 00000005517 14232154237 0024403 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/queue/queues"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := queues.NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
messagesClient := NewWithEnvironment(client.Environment)
messagesClient.Client = client.PrepareWithAuthorizer(messagesClient.Client, storageAuth)
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error creating queue: %s", err)
}
defer queuesClient.Delete(ctx, accountName, queueName)
input := PutInput{
Message: "ohhai",
}
putResp, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message in queue: %s", err)
}
messageId := (*putResp.QueueMessages)[0].MessageId
popReceipt := (*putResp.QueueMessages)[0].PopReceipt
_, err = messagesClient.Update(ctx, accountName, queueName, messageId, UpdateInput{
PopReceipt: popReceipt,
Message: "Updated message",
VisibilityTimeout: 65,
})
if err != nil {
t.Fatalf("Error updating: %s", err)
}
for i := 0; i < 5; i++ {
input := PutInput{
Message: fmt.Sprintf("Message %d", i),
}
_, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message %d in queue: %s", i, err)
}
}
peakedMessages, err := messagesClient.Peek(ctx, accountName, queueName, 3)
if err != nil {
t.Fatalf("Error peaking messages: %s", err)
}
for _, v := range *peakedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
}
retrievedMessages, err := messagesClient.Get(ctx, accountName, queueName, 6, GetInput{})
if err != nil {
t.Fatalf("Error retrieving messages: %s", err)
}
for _, v := range *retrievedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
_, err = messagesClient.Delete(ctx, accountName, queueName, v.MessageId, v.PopReceipt)
if err != nil {
t.Fatalf("Error deleting message from queue: %s", err)
}
}
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/models.go 0000664 0000000 0000000 00000001010 14232154237 0022650 0 ustar 00root root 0000000 0000000 package messages
import "github.com/Azure/go-autorest/autorest"
type QueueMessage struct {
MessageText string `xml:"MessageText"`
}
type QueueMessagesListResult struct {
autorest.Response
QueueMessages *[]QueueMessageResponse `xml:"QueueMessage"`
}
type QueueMessageResponse struct {
MessageId string `xml:"MessageId"`
InsertionTime string `xml:"InsertionTime"`
ExpirationTime string `xml:"ExpirationTime"`
PopReceipt string `xml:"PopReceipt"`
TimeNextVisible string `xml:"TimeNextVisible"`
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/peek.go 0000664 0000000 0000000 00000006512 14232154237 0022325 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Peek retrieves one or more messages from the front of the queue, but doesn't alter the visibility of the messages
func (client Client) Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Peek", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Peek", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Peek", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Peek", "`numberOfMessages` must be between 1 and 32.")
}
req, err := client.PeekPreparer(ctx, accountName, queueName, numberOfMessages)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", nil, "Failure preparing request")
return
}
resp, err := client.PeekSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure sending request")
return
}
result, err = client.PeekResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure responding to request")
return
}
return
}
// PeekPreparer prepares the Peek request.
func (client Client) PeekPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
"peekonly": autorest.Encode("query", true),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PeekSender sends the Peek request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PeekSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PeekResponder handles the response to the Peek request. The method always
// closes the http.Response Body.
func (client Client) PeekResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/put.go 0000664 0000000 0000000 00000010107 14232154237 0022204 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// The maximum time-to-live can be any positive number,
// as well as -1 indicating that the message does not expire.
// If this parameter is omitted, the default time-to-live is 7 days.
MessageTtl *int
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// visibilitytimeout should be set to a value smaller than the time-to-live value.
// If not specified, the default value is 0.
VisibilityTimeout *int
}
// Put adds a new message to the back of the message queue
func (client Client) Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Put", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Put", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Put", "`queueName` must be a lower-cased string.")
}
req, err := client.PutPreparer(ctx, accountName, queueName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", nil, "Failure preparing request")
return
}
resp, err := client.PutSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure sending request")
return
}
result, err = client.PutResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure responding to request")
return
}
return
}
// PutPreparer prepares the Put request.
func (client Client) PutPreparer(ctx context.Context, accountName, queueName string, input PutInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{}
if input.MessageTtl != nil {
queryParameters["messagettl"] = autorest.Encode("path", *input.MessageTtl)
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("path", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutSender sends the Put request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutResponder handles the response to the Put request. The method always
// closes the http.Response Body.
func (client Client) PutResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/resource_id.go 0000664 0000000 0000000 00000003044 14232154237 0023701 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Message within a Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName, messageID string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/messages/%s", domain, queueName, messageID)
}
type ResourceID struct {
AccountName string
QueueName string
MessageID string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Message within a Queue
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) != 3 {
return nil, fmt.Errorf("Expected the path to contain 3 segments but got %d", len(segments))
}
queueName := segments[0]
messageID := segments[2]
return &ResourceID{
AccountName: *accountName,
MessageID: messageID,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/resource_id_test.go 0000664 0000000 0000000 00000004321 14232154237 0024737 0 ustar 00root root 0000000 0000000 package messages
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1", "message1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected Queue Name to be `queue1` but got %q", actual.QueueName)
}
if actual.MessageID != "message1" {
t.Fatalf("Expected Message ID to be `message1` but got %q", actual.MessageID)
}
}
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/update.go 0000664 0000000 0000000 00000010071 14232154237 0022656 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type UpdateInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// Specifies the valid pop receipt value required to modify this message.
PopReceipt string
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// A message can be updated until it has been deleted or has expired.
VisibilityTimeout int
}
// Update updates an existing message based on it's Pop Receipt
func (client Client) Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Update", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Update", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Update", "`queueName` must be a lower-cased string.")
}
if input.PopReceipt == "" {
return result, validation.NewError("messages.Client", "Update", "`input.PopReceipt` cannot be an empty string.")
}
req, err := client.UpdatePreparer(ctx, accountName, queueName, messageID, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", nil, "Failure preparing request")
return
}
resp, err := client.UpdateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure sending request")
return
}
result, err = client.UpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure responding to request")
return
}
return
}
// UpdatePreparer prepares the Update request.
func (client Client) UpdatePreparer(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", input.PopReceipt),
"visibilitytimeout": autorest.Encode("query", input.VisibilityTimeout),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UpdateSender sends the Update request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UpdateResponder handles the response to the Update request. The method always
// closes the http.Response Body.
func (client Client) UpdateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/messages/version.go 0000664 0000000 0000000 00000000466 14232154237 0023070 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/ 0000775 0000000 0000000 00000000000 14232154237 0020546 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/queue/queues/README.md 0000664 0000000 0000000 00000002013 14232154237 0022021 0 ustar 00root root 0000000 0000000 ## Queue Storage Queues SDK for API version 2018-03-28
This package allows you to interact with the Queues Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/queue/queues"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
queuesClient := queues.New()
queuesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := queuesClient.Create(ctx, accountName, queueName, metadata); err != nil {
return fmt.Errorf("Error creating Queue: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/queue/queues/client.go 0000664 0000000 0000000 00000001126 14232154237 0022353 0 ustar 00root root 0000000 0000000 package queues
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Queue Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/create.go 0000664 0000000 0000000 00000006247 14232154237 0022351 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates the specified Queue within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Create", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Create", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Create", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/delete.go 0000664 0000000 0000000 00000005502 14232154237 0022341 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Queue within the specified Storage Account
func (client Client) Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Delete", "`queueName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/lifecycle_test.go 0000664 0000000 0000000 00000014127 14232154237 0024100 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestQueuesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
_, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
// first let's test an empty container
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
// then let's retrieve it to ensure there's no metadata..
resp, err := queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// then let's add some..
updatedMetaData := map[string]string{
"band": "panic",
"boots": "the-overpass",
}
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, updatedMetaData)
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error re-retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 2 {
t.Fatalf("Expected metadata to have 2 items but got: %s", resp.MetaData)
}
if resp.MetaData["band"] != "panic" {
t.Fatalf("Expected `band` to be `panic` but got: %s", resp.MetaData["band"])
}
if resp.MetaData["boots"] != "the-overpass" {
t.Fatalf("Expected `boots` to be `the-overpass` but got: %s", resp.MetaData["boots"])
}
// and woo let's remove it again
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// set some properties
props := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "GET,PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
CorsRule{
AllowedMethods: "POST",
AllowedOrigins: "http://www.test.com",
ExposedHeaders: "*",
AllowedHeaders: "x-method-*",
MaxAgeInSeconds: 200,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err := queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) > 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "GET,PUT" {
t.Fatalf("CORS Methods weren't set!")
}
if properties.Cors.CorsRule[1].AllowedMethods != "POST" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
includeAPIS := true
// set some properties
props2 := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
IncludeAPIs: &includeAPIS,
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props2)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err = queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) == 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "PUT" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if !properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
log.Printf("[DEBUG] Deleting..")
_, err = queuesClient.Delete(ctx, accountName, queueName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/metadata_get.go 0000664 0000000 0000000 00000006376 14232154237 0023530 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the metadata for this Queue
func (client Client) GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/metadata_set.go 0000664 0000000 0000000 00000006576 14232154237 0023546 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData returns the metadata for this Queue
func (client Client) SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/models.go 0000664 0000000 0000000 00000002410 14232154237 0022355 0 ustar 00root root 0000000 0000000 package queues
type StorageServiceProperties struct {
Logging *LoggingConfig `xml:"Logging,omitempty"`
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
Cors *Cors `xml:"Cors,omitempty"`
}
type LoggingConfig struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
}
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
// Element IncludeAPIs is only expected when Metrics is enabled
IncludeAPIs *bool `xml:"IncludeAPIs,omitempty"`
}
type RetentionPolicy struct {
Enabled bool `xml:"Enabled"`
Days int `xml:"Days,omitempty"`
}
type Cors struct {
CorsRule []CorsRule `xml:"CorsRule"`
}
type CorsRule struct {
AllowedOrigins string `xml:"AllowedOrigins"`
AllowedMethods string `xml:"AllowedMethods"`
AllowedHeaders string `xml:"AllowedHeaders`
ExposedHeaders string `xml:"ExposedHeaders"`
MaxAgeInSeconds int `xml:"MaxAgeInSeconds"`
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/properties_get.go 0000664 0000000 0000000 00000005670 14232154237 0024140 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type StorageServicePropertiesResponse struct {
StorageServiceProperties
autorest.Response
}
// SetServiceProperties gets the properties for this queue
func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result StorageServicePropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.GetServicePropertiesPreparer(ctx, accountName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.GetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// GetServicePropertiesPreparer prepares the GetServiceProperties request.
func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetServicePropertiesSender sends the GetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetServicePropertiesResponder handles the response to the GetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) GetServicePropertiesResponder(resp *http.Response) (result StorageServicePropertiesResponse, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/properties_set.go 0000664 0000000 0000000 00000005575 14232154237 0024160 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetServiceProperties sets the properties for this queue
func (client Client) SetServiceProperties(ctx context.Context, accountName string, properties StorageServiceProperties) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.SetServicePropertiesPreparer(ctx, accountName, properties)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetServicePropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.SetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// SetServicePropertiesPreparer prepares the SetServiceProperties request.
func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, properties StorageServiceProperties) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(properties),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) SetServicePropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/resource_id.go 0000664 0000000 0000000 00000002315 14232154237 0023401 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, queueName)
}
type ResourceID struct {
AccountName string
QueueName string
}
// ParseResourceID parses the Resource ID and returns an Object which
// can be used to interact with a Queue within a Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.queue.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
queueName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/resource_id_test.go 0000664 0000000 0000000 00000003701 14232154237 0024440 0 ustar 00root root 0000000 0000000 package queues
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected the queue name to be `queue1` but got %q", actual.QueueName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/queue/queues/version.go 0000664 0000000 0000000 00000000464 14232154237 0022566 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/table/ 0000775 0000000 0000000 00000000000 14232154237 0017202 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/table/entities/ 0000775 0000000 0000000 00000000000 14232154237 0021026 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/table/entities/README.md 0000664 0000000 0000000 00000002166 14232154237 0022312 0 ustar 00root root 0000000 0000000 ## Table Storage Entities SDK for API version 2018-03-28
This package allows you to interact with the Entities Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/table/entities"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
entitiesClient := entities.New()
entitiesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := entities.InsertEntityInput{
PartitionKey: "abc",
RowKey: "123",
MetaDataLevel: entities.NoMetaData,
Entity: map[string]interface{}{
"title": "Don't Kill My Vibe",
"artist": "Sigrid",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, input); err != nil {
return fmt.Errorf("Error creating Entity: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/table/entities/client.go 0000664 0000000 0000000 00000001130 14232154237 0022626 0 ustar 00root root 0000000 0000000 package entities
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/table/entities/delete.go 0000664 0000000 0000000 00000007327 14232154237 0022630 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteEntityInput struct {
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Delete deletes an existing entity in a table.
func (client Client) Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Delete", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.RowKey` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
// TODO: support for eTags
"If-Match": "*",
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/entities/get.go 0000664 0000000 0000000 00000007013 14232154237 0022135 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetEntityInput struct {
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
}
type GetEntityResult struct {
autorest.Response
Entity map[string]interface{}
}
// Get queries entities in a table and includes the $filter and $select options.
func (client Client) Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Get", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Get", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.RowKey` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, tableName string, input GetEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetEntityResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result.Entity),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/entities/insert.go 0000664 0000000 0000000 00000010207 14232154237 0022661 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertEntityInput struct {
// The level of MetaData provided for this Entity
MetaDataLevel MetaDataLevel
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Insert inserts a new entity into a table.
func (client Client) Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Insert", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Insert", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", nil, "Failure preparing request")
return
}
resp, err := client.InsertSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure sending request")
return
}
result, err = client.InsertResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure responding to request")
return
}
return
}
// InsertPreparer prepares the Insert request.
func (client Client) InsertPreparer(ctx context.Context, accountName, tableName string, input InsertEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"Prefer": "return-no-content",
}
input.Entity["PartitionKey"] = input.PartitionKey
input.Entity["RowKey"] = input.RowKey
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertSender sends the Insert request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertResponder handles the response to the Insert request. The method always
// closes the http.Response Body.
func (client Client) InsertResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/entities/insert_or_merge.go 0000664 0000000 0000000 00000010625 14232154237 0024544 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrMergeEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrMerge updates an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrMergePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrMergeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure sending request")
return
}
result, err = client.InsertOrMergeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure responding to request")
return
}
return
}
// InsertOrMergePreparer prepares the InsertOrMerge request.
func (client Client) InsertOrMergePreparer(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrMergeSender sends the InsertOrMerge request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrMergeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrMergeResponder handles the response to the InsertOrMerge request. The method always
// closes the http.Response Body.
func (client Client) InsertOrMergeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/entities/insert_or_replace.go 0000664 0000000 0000000 00000010706 14232154237 0025060 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrReplaceEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrReplace replaces an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrReplacePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrReplaceSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure sending request")
return
}
result, err = client.InsertOrReplaceResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure responding to request")
return
}
return
}
// InsertOrReplacePreparer prepares the InsertOrReplace request.
func (client Client) InsertOrReplacePreparer(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrReplaceSender sends the InsertOrReplace request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrReplaceSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrReplaceResponder handles the response to the InsertOrReplace request. The method always
// closes the http.Response Body.
func (client Client) InsertOrReplaceResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/entities/lifecycle_test.go 0000664 0000000 0000000 00000010135 14232154237 0024353 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/table/tables"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestEntitiesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := tables.NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
defer tablesClient.Delete(ctx, accountName, tableName)
entitiesClient := NewWithEnvironment(client.Environment)
entitiesClient.Client = client.PrepareWithAuthorizer(entitiesClient.Client, storageAuth)
partitionKey := "hello"
rowKey := "there"
t.Logf("[DEBUG] Inserting..")
insertInput := InsertEntityInput{
MetaDataLevel: NoMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "world",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, insertInput); err != nil {
t.Logf("Error retrieving: %s", err)
}
t.Logf("[DEBUG] Insert or Merging..")
insertOrMergeInput := InsertOrMergeEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "ther88e",
},
}
if _, err := entitiesClient.InsertOrMerge(ctx, accountName, tableName, insertOrMergeInput); err != nil {
t.Logf("Error insert/merging: %s", err)
}
t.Logf("[DEBUG] Insert or Replacing..")
insertOrReplaceInput := InsertOrReplaceEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "pandas",
},
}
if _, err := entitiesClient.InsertOrReplace(ctx, accountName, tableName, insertOrReplaceInput); err != nil {
t.Logf("Error inserting/replacing: %s", err)
}
t.Logf("[DEBUG] Querying..")
queryInput := QueryEntitiesInput{
MetaDataLevel: NoMetaData,
}
results, err := entitiesClient.Query(ctx, accountName, tableName, queryInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
if len(results.Entities) != 1 {
t.Fatalf("Expected 1 item but got %d", len(results.Entities))
}
for _, v := range results.Entities {
thisPartitionKey := v["PartitionKey"].(string)
thisRowKey := v["RowKey"].(string)
if partitionKey != thisPartitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, thisPartitionKey)
}
if rowKey != thisRowKey {
t.Fatalf("Expected Partition Key to be %q but got %q", rowKey, thisRowKey)
}
}
t.Logf("[DEBUG] Retrieving..")
getInput := GetEntityInput{
MetaDataLevel: MinimalMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
}
getResults, err := entitiesClient.Get(ctx, accountName, tableName, getInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
partitionKey2 := getResults.Entity["PartitionKey"].(string)
rowKey2 := getResults.Entity["RowKey"].(string)
if partitionKey2 != partitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, partitionKey2)
}
if rowKey2 != rowKey {
t.Fatalf("Expected Row Key to be %q but got %q", rowKey, rowKey2)
}
t.Logf("[DEBUG] Deleting..")
deleteInput := DeleteEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
}
if _, err := entitiesClient.Delete(ctx, accountName, tableName, deleteInput); err != nil {
t.Logf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-03-28/table/entities/models.go 0000664 0000000 0000000 00000000306 14232154237 0022637 0 ustar 00root root 0000000 0000000 package entities
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
giovanni-0.20.0/storage/2018-03-28/table/entities/query.go 0000664 0000000 0000000 00000012065 14232154237 0022526 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type QueryEntitiesInput struct {
// An optional OData filter
Filter *string
// An optional comma-separated
PropertyNamesToSelect *[]string
// An optional OData top
Top *int
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
// The Next Partition Key used to load data from a previous point
NextPartitionKey *string
// The Next Row Key used to load data from a previous point
NextRowKey *string
}
type QueryEntitiesResult struct {
autorest.Response
NextPartitionKey string
NextRowKey string
MetaData string `json:"odata.metadata,omitempty"`
Entities []map[string]interface{} `json:"value"`
}
// Query queries entities in a table and includes the $filter and $select options.
func (client Client) Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Query", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Query", "`tableName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"additionalParameters": "",
}
//PartitionKey='',RowKey=''
additionalParams := make([]string, 0)
if input.PartitionKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("PartitionKey='%s'", input.PartitionKey))
}
if input.RowKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("RowKey='%s'", input.RowKey))
}
if len(additionalParams) > 0 {
pathParameters["additionalParameters"] = autorest.Encode("path", strings.Join(additionalParams, ","))
}
queryParameters := map[string]interface{}{}
if input.Filter != nil {
queryParameters["$filter"] = autorest.Encode("query", *input.Filter)
}
if input.PropertyNamesToSelect != nil {
queryParameters["$select"] = autorest.Encode("query", strings.Join(*input.PropertyNamesToSelect, ","))
}
if input.Top != nil {
queryParameters["$top"] = autorest.Encode("query", *input.Top)
}
if input.NextPartitionKey != nil {
queryParameters["NextPartitionKey"] = *input.NextPartitionKey
}
if input.NextRowKey != nil {
queryParameters["NextRowKey"] = *input.NextRowKey
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
// GET /myaccount/Customers()?$filter=(Rating%20ge%203)%20and%20(Rating%20le%206)&$select=PartitionKey,RowKey,Address,CustomerSince
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}({additionalParameters})", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result QueryEntitiesResult, err error) {
if resp != nil && resp.Header != nil {
result.NextPartitionKey = resp.Header.Get("x-ms-continuation-NextPartitionKey")
result.NextRowKey = resp.Header.Get("x-ms-continuation-NextRowKey")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/entities/resource_id.go 0000664 0000000 0000000 00000005370 14232154237 0023665 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Entity
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName, partitionKey, rowKey string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s(PartitionKey='%s',RowKey='%s')", domain, tableName, partitionKey, rowKey)
}
type ResourceID struct {
AccountName string
TableName string
PartitionKey string
RowKey string
}
// ParseResourceID parses the specified Resource ID and returns an object which
// can be used to look up the specified Entity within the specified Table
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.Contains(uri.Path, "(") || !strings.HasSuffix(uri.Path, ")") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `tables(PartitionKey='',RowKey='')` but got %q", path)
}
// NOTE: honestly this could probably be a RegEx, but this seemed like the simplest way to
// allow these two fields to be specified in either order
indexOfBracket := strings.IndexByte(path, '(')
tableName := path[0:indexOfBracket]
// trim off the brackets
temp := strings.TrimPrefix(path, fmt.Sprintf("%s(", tableName))
temp = strings.TrimSuffix(temp, ")")
dictionary := strings.Split(temp, ",")
partitionKey := ""
rowKey := ""
for _, v := range dictionary {
split := strings.Split(v, "=")
if len(split) != 2 {
return nil, fmt.Errorf("Expected 2 segments but got %d for %q", len(split), v)
}
key := split[0]
value := strings.TrimSuffix(strings.TrimPrefix(split[1], "'"), "'")
if strings.EqualFold(key, "PartitionKey") {
partitionKey = value
} else if strings.EqualFold(key, "RowKey") {
rowKey = value
} else {
return nil, fmt.Errorf("Unexpected Key %q", key)
}
}
if partitionKey == "" {
return nil, fmt.Errorf("Expected a PartitionKey but didn't get one")
}
if rowKey == "" {
return nil, fmt.Errorf("Expected a RowKey but didn't get one")
}
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
PartitionKey: partitionKey,
RowKey: rowKey,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/table/entities/resource_id_test.go 0000664 0000000 0000000 00000005012 14232154237 0024715 0 ustar 00root root 0000000 0000000 package entities
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1", "partition1", "row1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
if actual.PartitionKey != "partition1" {
t.Fatalf("Expected Partition Key to be `partition1` but got %q", actual.PartitionKey)
}
if actual.RowKey != "row1" {
t.Fatalf("Expected Row Key to be `row1` but got %q", actual.RowKey)
}
}
}
giovanni-0.20.0/storage/2018-03-28/table/entities/version.go 0000664 0000000 0000000 00000000466 14232154237 0023050 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-03-28/table/tables/ 0000775 0000000 0000000 00000000000 14232154237 0020454 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-03-28/table/tables/README.md 0000664 0000000 0000000 00000001550 14232154237 0021734 0 ustar 00root root 0000000 0000000 ## Table Storage Tables SDK for API version 2018-03-28
This package allows you to interact with the Tables Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-03-28/table/tables"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
tablesClient := tables.New()
tablesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
if _, err := tablesClient.Insert(ctx, accountName, tableName); err != nil {
return fmt.Errorf("Error creating Table: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-03-28/table/tables/acl_get.go 0000664 0000000 0000000 00000005654 14232154237 0022413 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL returns the Access Control List for the specified Table
func (client Client) GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`tableName` cannot be an empty string.")
}
req, err := client.GetACLPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/tables/acl_set.go 0000664 0000000 0000000 00000006062 14232154237 0022421 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"encoding/xml"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List for the specified Table
func (client Client) SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`tableName` cannot be an empty string.")
}
req, err := client.SetACLPreparer(ctx, accountName, tableName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/tables/client.go 0000664 0000000 0000000 00000001126 14232154237 0022261 0 ustar 00root root 0000000 0000000 package tables
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-03-28/table/tables/create.go 0000664 0000000 0000000 00000005571 14232154237 0022256 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type createTableRequest struct {
TableName string `json:"TableName"`
}
// Create creates a new table in the storage account.
func (client Client) Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Create", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Create", "`tableName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// NOTE: we could support returning metadata here, but it doesn't appear to be directly useful
// vs making a request using the Get methods as-necessary?
"Accept": "application/json;odata=nometadata",
"Prefer": "return-no-content",
}
body := createTableRequest{
TableName: tableName,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithJSON(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/tables/delete.go 0000664 0000000 0000000 00000005260 14232154237 0022250 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified table and any data it contains.
func (client Client) Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Delete", "`tableName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/tables/exists.go 0000664 0000000 0000000 00000005304 14232154237 0022324 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Exists checks that the specified table exists
func (client Client) Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Exists", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Exists", "`tableName` cannot be an empty string.")
}
req, err := client.ExistsPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", nil, "Failure preparing request")
return
}
resp, err := client.ExistsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure sending request")
return
}
result, err = client.ExistsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure responding to request")
return
}
return
}
// ExistsPreparer prepares the Exists request.
func (client Client) ExistsPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.AsContentType("application/xml"),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ExistsSender sends the Exists request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ExistsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ExistsResponder handles the response to the Exists request. The method always
// closes the http.Response Body.
func (client Client) ExistsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/tables/lifecycle_test.go 0000664 0000000 0000000 00000007175 14232154237 0024013 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestTablesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
// first look it up directly and confirm it's there
t.Logf("[DEBUG] Checking if Table exists..")
if _, err := tablesClient.Exists(ctx, accountName, tableName); err != nil {
t.Fatalf("Error checking if Table %q exists: %s", tableName, err)
}
// then confirm it exists in the Query too
t.Logf("[DEBUG] Querying for Tables..")
result, err := tablesClient.Query(ctx, accountName, NoMetaData)
if err != nil {
t.Fatalf("Error retrieving Tables: %s", err)
}
found := false
for _, v := range result.Tables {
log.Printf("[DEBUG] Table: %q", v.TableName)
if v.TableName == tableName {
found = true
}
}
if !found {
t.Fatalf("%q was not found in the Query response!", tableName)
}
t.Logf("[DEBUG] Setting ACL's for Table %q..", tableName)
acls := []SignedIdentifier{
{
Id: "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=",
AccessPolicy: AccessPolicy{
Permission: "raud",
Start: "2020-11-26T08:49:37.0000000Z",
Expiry: "2020-11-27T08:49:37.0000000Z",
},
},
}
if _, err := tablesClient.SetACL(ctx, accountName, tableName, acls); err != nil {
t.Fatalf("Error setting ACLs: %s", err)
}
t.Logf("[DEBUG] Retrieving ACL's for Table %q..", tableName)
retrievedACLs, err := tablesClient.GetACL(ctx, accountName, tableName)
if err != nil {
t.Fatalf("Error retrieving ACLs: %s", err)
}
if len(retrievedACLs.SignedIdentifiers) != len(acls) {
t.Fatalf("Expected %d but got %q ACLs", len(retrievedACLs.SignedIdentifiers), len(acls))
}
for i, retrievedAcl := range retrievedACLs.SignedIdentifiers {
expectedAcl := acls[i]
if retrievedAcl.Id != expectedAcl.Id {
t.Fatalf("Expected ID to be %q but got %q", retrievedAcl.Id, expectedAcl.Id)
}
if retrievedAcl.AccessPolicy.Start != expectedAcl.AccessPolicy.Start {
t.Fatalf("Expected Start to be %q but got %q", retrievedAcl.AccessPolicy.Start, expectedAcl.AccessPolicy.Start)
}
if retrievedAcl.AccessPolicy.Expiry != expectedAcl.AccessPolicy.Expiry {
t.Fatalf("Expected Expiry to be %q but got %q", retrievedAcl.AccessPolicy.Expiry, expectedAcl.AccessPolicy.Expiry)
}
if retrievedAcl.AccessPolicy.Permission != expectedAcl.AccessPolicy.Permission {
t.Fatalf("Expected Permission to be %q but got %q", retrievedAcl.AccessPolicy.Permission, expectedAcl.AccessPolicy.Permission)
}
}
t.Logf("[DEBUG] Deleting Table %q..", tableName)
if _, err := tablesClient.Delete(ctx, accountName, tableName); err != nil {
t.Fatalf("Error deleting %q: %s", tableName, err)
}
}
giovanni-0.20.0/storage/2018-03-28/table/tables/models.go 0000664 0000000 0000000 00000001324 14232154237 0022266 0 ustar 00root root 0000000 0000000 package tables
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
type GetResultItem struct {
TableName string `json:"TableName"`
// Optional, depending on the MetaData Level
ODataType string `json:"odata.type,omitempty"`
ODataID string `json:"odata.id,omitEmpty"`
ODataEditLink string `json:"odata.editLink,omitEmpty"`
}
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2018-03-28/table/tables/query.go 0000664 0000000 0000000 00000005430 14232154237 0022152 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetResult struct {
autorest.Response
MetaData string `json:"odata.metadata,omitempty"`
Tables []GetResultItem `json:"value"`
}
// Query returns a list of tables under the specified account.
func (client Client) Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Query", "`accountName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, metaDataLevel)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (*http.Request, error) {
// NOTE: whilst this supports ContinuationTokens and 'Top'
// it appears that 'Skip' returns a '501 Not Implemented'
// as such, we intentionally don't support those right now
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", metaDataLevel),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result GetResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-03-28/table/tables/resource_id.go 0000664 0000000 0000000 00000003112 14232154237 0023303 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Table
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/Tables('%s')", domain, tableName)
}
type ResourceID struct {
AccountName string
TableName string
}
// ParseResourceID parses the Resource ID and returns an object which
// can be used to interact with the Table within the specified Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.table.core.windows.net/Table('foo')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.HasPrefix(path, "Tables('") || !strings.HasSuffix(path, "')") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `Tables('name')` but got %q", path)
}
// strip off the `Table('')`
tableName := strings.TrimPrefix(uri.Path, "/Tables('")
tableName = strings.TrimSuffix(tableName, "')")
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
}, nil
}
giovanni-0.20.0/storage/2018-03-28/table/tables/resource_id_test.go 0000664 0000000 0000000 00000004010 14232154237 0024340 0 ustar 00root root 0000000 0000000 package tables
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
}
}
giovanni-0.20.0/storage/2018-03-28/table/tables/version.go 0000664 0000000 0000000 00000000464 14232154237 0022474 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-03-28"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/ 0000775 0000000 0000000 00000000000 14232154237 0016111 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/README.md 0000664 0000000 0000000 00000001215 14232154237 0017367 0 ustar 00root root 0000000 0000000 # Storage API Version 2018-11-09
The following API's are supported by this SDK - more information about each SDK can be found within the README in each package.
## Blob Storage
- [Blobs API](blob/blobs)
- [Containers API](blob/containers)
- [Accounts API](blob/accounts)
## DataLakeStore Gen2
- [FileSystems API](datalakestore/filesystems)
- [Paths API](datalakestore/paths)
## File Storage
- [Directories API](file/directories)
- [Files API](file/files)
- [Shares API](file/shares)
## Queue Storage
- [Queues API](queue/queues)
- [Messages API](queue/messages)
## Table Storage
- [Entities API](table/entities)
- [Tables API](table/tables)
giovanni-0.20.0/storage/2018-11-09/blob/ 0000775 0000000 0000000 00000000000 14232154237 0017027 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/blob/accounts/ 0000775 0000000 0000000 00000000000 14232154237 0020646 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/blob/accounts/README.md 0000664 0000000 0000000 00000002463 14232154237 0022132 0 ustar 00root root 0000000 0000000 ## Blob Storage Account SDK for API version 2018-11-09
This package allows you to interact with the Accounts Blob Storage API
### Supported Authorizers
* Azure Active Directory
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts"
)
func Example() error {
accountName := "storageaccount1"
// e.g. https://github.com/tombuildsstuff/giovanni/blob/76f5f686c99ecdcc3fa533a0330d0e1aacb1c327/example/azuread-auth/main.go#L54
client, err := buildClient()
if err != nil {
return fmt.Errorf("error building client: %s", err)
}
ctx := context.TODO()
input := StorageServiceProperties{
StaticWebsite: &StaticWebsite{
Enabled: true,
IndexDocument: index,
ErrorDocument404Path: errorDocument,
},
}
_, err = client.SetServiceProperties(ctx, accountName, input)
if err != nil {
return fmt.Errorf("error setting properties: %s", err)
}
time.Sleep(2 * time.Second)
_, err = accountsClient.GetServiceProperties(ctx, accountName)
if err != nil {
return fmt.Errorf("error getting properties: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/blob/accounts/client.go 0000664 0000000 0000000 00000001122 14232154237 0022447 0 ustar 00root root 0000000 0000000 package accounts
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/blob/accounts/get_service_properties.go 0000664 0000000 0000000 00000005205 14232154237 0025752 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetServicePropertiesResult struct {
autorest.Response
ContentType string
StorageServiceProperties *StorageServiceProperties
}
// GetServicePropertiesPreparer prepares the GetServiceProperties request.
func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) {
queryParameters := map[string]interface{}{
"restype": "service",
"comp": "properties",
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
func (client Client) GetServicePropertiesResponder(resp *http.Response) (result GetServicePropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result.StorageServiceProperties),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result GetServicePropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("accounts.Client", "GetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.GetServicePropertiesPreparer(ctx, accountName)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.GetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure responding to request")
return
}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/accounts/models.go 0000664 0000000 0000000 00000011115 14232154237 0022457 0 ustar 00root root 0000000 0000000 package accounts
import "github.com/Azure/go-autorest/autorest"
type SetServicePropertiesResult struct {
autorest.Response
}
type StorageServiceProperties struct {
// Cors - Specifies CORS rules for the Blob service. You can include up to five CorsRule elements in the request. If no CorsRule elements are included in the request body, all CORS rules will be deleted, and CORS will be disabled for the Blob service.
Cors *CorsRules `xml:"Cors,omitempty"`
// DefaultServiceVersion - DefaultServiceVersion indicates the default version to use for requests to the Blob service if an incoming request’s version is not specified. Possible values include version 2008-10-27 and all more recent versions.
DefaultServiceVersion *string `xml:"DefaultServiceVersion,omitempty"`
// DeleteRetentionPolicy - The blob service properties for soft delete.
DeleteRetentionPolicy *DeleteRetentionPolicy `xml:"DeleteRetentionPolicy,omitempty"`
// Logging - The blob service properties for logging access
Logging *Logging `xml:"Logging,omitempty"`
// HourMetrics - The blob service properties for hour metrics
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
// HourMetrics - The blob service properties for minute metrics
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
// StaticWebsite - Optional
StaticWebsite *StaticWebsite `xml:"StaticWebsite,omitempty"`
}
// StaticWebsite sets the static website support properties on the Blob service.
type StaticWebsite struct {
// Enabled - Required. Indicates whether static website support is enabled for the given account.
Enabled bool `xml:"Enabled"`
// IndexDocument - Optional. The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive.
IndexDocument string `xml:"IndexDocument,omitempty"`
// ErrorDocument404Path - Optional. The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive.
ErrorDocument404Path string `xml:"ErrorDocument404Path,omitempty"`
}
// CorsRules sets the CORS rules. You can include up to five CorsRule elements in the request.
type CorsRules struct {
// CorsRules - The List of CORS rules. You can include up to five CorsRule elements in the request.
CorsRules []CorsRule `xml:"CorsRules,omitempty"`
}
// DeleteRetentionPolicy the blob service properties for soft delete.
type DeleteRetentionPolicy struct {
// Enabled - Indicates whether DeleteRetentionPolicy is enabled for the Blob service.
Enabled bool `xml:"Enabled,omitempty"`
// Days - Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365.
Days int32 `xml:"Days,omitempty"`
}
// CorsRule specifies a CORS rule for the Blob service.
type CorsRule struct {
// AllowedOrigins - Required if CorsRule element is present. A list of origin domains that will be allowed via CORS, or "" to allow all domains
AllowedOrigins []string `xml:"AllowedOrigins,omitempty"`
// AllowedMethods - Required if CorsRule element is present. A list of HTTP methods that are allowed to be executed by the origin.
AllowedMethods []string `xml:"AllowedMethods,omitempty"`
// MaxAgeInSeconds - Required if CorsRule element is present. The number of seconds that the client/browser should cache a preflight response.
MaxAgeInSeconds int32 `xml:"MaxAgeInSeconds,omitempty"`
// ExposedHeaders - Required if CorsRule element is present. A list of response headers to expose to CORS clients.
ExposedHeaders []string `xml:"ExposedHeaders,omitempty"`
// AllowedHeaders - Required if CorsRule element is present. A list of headers allowed to be part of the cross-origin request.
AllowedHeaders []string `xml:"AllowedHeaders,omitempty"`
}
// Logging specifies the access logging options for the Blob service.
type Logging struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy DeleteRetentionPolicy `xml:"RetentionPolicy"`
}
// MetricsConfig specifies the hour and/or minute metrics options for the Blob service.
// Elements are all expected
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy DeleteRetentionPolicy `xml:"RetentionPolicy"`
IncludeAPIs bool `xml:"IncludeAPIs"`
}
giovanni-0.20.0/storage/2018-11-09/blob/accounts/set_service_properties.go 0000664 0000000 0000000 00000005322 14232154237 0025766 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetServicePropertiesPreparer prepares the SetServiceProperties request.
func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, input StorageServiceProperties) (*http.Request, error) {
queryParameters := map[string]interface{}{
"restype": "service",
"comp": "properties",
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithHeaders(headers),
autorest.WithXML(input),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) SetServicePropertiesResponder(resp *http.Response) (result SetServicePropertiesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
func (client Client) SetServiceProperties(ctx context.Context, accountName string, input StorageServiceProperties) (result SetServicePropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("accounts.Client", "SetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.SetServicePropertiesPreparer(ctx, accountName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.SetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure responding to request")
return
}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/accounts/set_service_properties_test.go 0000664 0000000 0000000 00000005316 14232154237 0027030 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
_, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
accountsClient := NewWithEnvironment(client.Environment)
accountsClient.Client = client.PrepareWithStorageResourceManagerAuth(accountsClient.Client)
input := StorageServiceProperties{}
_, err = accountsClient.SetServiceProperties(ctx, accountName, input)
if err != nil {
t.Fatal(fmt.Errorf("error setting properties: %s", err))
}
var index = "index.html"
//var enabled = true
var errorDocument = "404.html"
input = StorageServiceProperties{
StaticWebsite: &StaticWebsite{
Enabled: true,
IndexDocument: index,
ErrorDocument404Path: errorDocument,
},
Logging: &Logging{
Version: "2.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: DeleteRetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = accountsClient.SetServiceProperties(ctx, accountName, input)
if err != nil {
t.Fatal(fmt.Errorf("error setting properties: %s", err))
}
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
result, err := accountsClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatal(fmt.Errorf("error getting properties: %s", err))
}
website := result.StorageServiceProperties.StaticWebsite
if website.Enabled != true {
t.Fatalf("Expected the StaticWebsite %t but got %t", true, website.Enabled)
}
logging := result.StorageServiceProperties.Logging
if logging.Version != "2.0" {
t.Fatalf("Expected the Logging Version %s but got %s", "2.0", logging.Version)
}
if !logging.Read {
t.Fatalf("Expected the Logging Read %t but got %t", true, logging.Read)
}
if !logging.Write {
t.Fatalf("Expected the Logging Write %t but got %t", true, logging.Write)
}
if !logging.Delete {
t.Fatalf("Expected the Logging Delete %t but got %t", true, logging.Delete)
}
if !logging.RetentionPolicy.Enabled {
t.Fatalf("Expected the Logging RetentionPolicy.Enabled %t but got %t", true, logging.RetentionPolicy.Enabled)
}
if logging.RetentionPolicy.Days != 7 {
t.Fatalf("Expected the Logging RetentionPolicy.Enabled %d but got %d", 7, logging.RetentionPolicy.Days)
}
}
giovanni-0.20.0/storage/2018-11-09/blob/accounts/version.go 0000664 0000000 0000000 00000000466 14232154237 0022670 0 ustar 00root root 0000000 0000000 package accounts
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/ 0000775 0000000 0000000 00000000000 14232154237 0020130 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/blob/blobs/README.md 0000664 0000000 0000000 00000002263 14232154237 0021412 0 ustar 00root root 0000000 0000000 ## Blob Storage Blobs SDK for API version 2018-11-09
This package allows you to interact with the Blobs Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
fileName := "example-large-file.iso"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
blobClient := blobs.New()
blobClient.Client.Authorizer = storageAuth
ctx := context.TODO()
copyInput := blobs.CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/blob/blobs/api.go 0000664 0000000 0000000 00000011051 14232154237 0021226 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
)
type StorageBlob interface {
AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error)
Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error)
AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error)
CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error
Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error)
DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error)
DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error)
Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error)
GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error)
GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error)
IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error)
AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error)
BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error)
ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error)
ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error)
RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error)
SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error)
GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error)
SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error)
PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error)
PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error)
PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error)
PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error
PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error)
PutBlockFromURL(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (result PutBlockFromURLResult, err error)
PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error)
PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error)
PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error)
GetResourceID(accountName, containerName, blobName string) string
SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error)
Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error)
GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error)
Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/append_block.go 0000664 0000000 0000000 00000014462 14232154237 0023107 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AppendBlockInput struct {
// 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 an AppendPositionConditionNotMet
// error (HTTP status code 412 – Precondition Failed)
BlobConditionAppendPosition *int64
// 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
// an MaxBlobSizeConditionNotMet error (HTTP status code 412 – Precondition Failed).
BlobConditionMaxSize *int64
// The Bytes which should be appended to the end of this Append Blob.
// This can either be nil, which creates an empty blob, or a byte array
Content *[]byte
// An MD5 hash of the block content.
// This hash is used to verify the integrity of the block during transport.
// When this header is specified, the storage service compares the hash of the content
// that has arrived with this header value.
//
// Note that this MD5 hash is not stored with the blob.
// If the two hashes do not match, the operation will fail with error code 400 (Bad Request).
ContentMD5 *string
// Required if the blob has an active lease.
// To perform this operation on a blob with an active lease, specify the valid lease ID for this header.
LeaseID *string
}
type AppendBlockResult struct {
autorest.Response
BlobAppendOffset string
BlobCommittedBlockCount int64
ContentMD5 string
ETag string
LastModified string
}
// AppendBlock commits a new block of data to the end of an existing append blob.
func (client Client) AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) > (4*1024*1024) {
return result, validation.NewError("files.Client", "PutByteRange", "`input.Content` must be at most 4MB.")
}
req, err := client.AppendBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", nil, "Failure preparing request")
return
}
resp, err := client.AppendBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure sending request")
return
}
result, err = client.AppendBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure responding to request")
return
}
return
}
// AppendBlockPreparer prepares the AppendBlock request.
func (client Client) AppendBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "appendblock"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.BlobConditionAppendPosition != nil {
headers["x-ms-blob-condition-appendpos"] = *input.BlobConditionAppendPosition
}
if input.BlobConditionMaxSize != nil {
headers["x-ms-blob-condition-maxsize"] = *input.BlobConditionMaxSize
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AppendBlockSender sends the AppendBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AppendBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AppendBlockResponder handles the response to the AppendBlock request. The method always
// closes the http.Response Body.
func (client Client) AppendBlockResponder(resp *http.Response) (result AppendBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobAppendOffset = resp.Header.Get("x-ms-blob-append-offset")
result.ContentMD5 = resp.Header.Get("ETag")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
if v := resp.Header.Get("x-ms-blob-committed-block-count"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
result.BlobCommittedBlockCount = int64(i)
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/blob_append_test.go 0000664 0000000 0000000 00000011330 14232154237 0023761 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestAppendBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Append Blob..")
if _, err := blobClient.PutAppendBlob(ctx, accountName, containerName, fileName, PutAppendBlobInput{}); err != nil {
t.Fatalf("Error putting append blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 0 {
t.Fatalf("Expected Content-Length to be 0 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending First Block..")
appendInput := AppendBlockInput{
Content: &[]byte{
12,
48,
93,
76,
29,
10,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending first block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 6 {
t.Fatalf("Expected Content-Length to be 6 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending Second Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
92,
62,
64,
47,
83,
77,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Second block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 12 {
t.Fatalf("Expected Content-Length to be 12 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Acquiring Lease..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error acquiring Lease: %s", err)
}
t.Logf("[DEBUG] Lease ID is %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Appending Third Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
64,
35,
28,
93,
11,
23,
},
LeaseID: &leaseDetails.LeaseID,
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Third block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 18 {
t.Fatalf("Expected Content-Length to be 18 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Breaking Lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseDetails.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
t.Logf("[DEBUG] Deleting Lease..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/blob_page_test.go 0000664 0000000 0000000 00000005541 14232154237 0023435 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPageBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Page Blob..")
fileSize := int64(10240000)
if _, err := blobClient.PutPageBlob(ctx, accountName, containerName, fileName, PutPageBlobInput{
BlobContentLengthBytes: fileSize,
}); err != nil {
t.Fatalf("Error putting page blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != fileSize {
t.Fatalf("Expected Content-Length to be %d but it was %d", fileSize, props.ContentLength)
}
for iteration := 1; iteration <= 3; iteration++ {
t.Logf("[DEBUG] Putting Page %d of 3..", iteration)
byteArray := func() []byte {
o := make([]byte, 0)
for i := 0; i < 512; i++ {
o = append(o, byte(i))
}
return o
}()
startByte := int64(512 * iteration)
endByte := int64(startByte + 511)
putPageInput := PutPageUpdateInput{
StartByte: startByte,
EndByte: endByte,
Content: byteArray,
}
if _, err := blobClient.PutPageUpdate(ctx, accountName, containerName, fileName, putPageInput); err != nil {
t.Fatalf("Error putting page: %s", err)
}
}
t.Logf("[DEBUG] Deleting..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/client.go 0000664 0000000 0000000 00000001117 14232154237 0021735 0 ustar 00root root 0000000 0000000 package blobs
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/copy.go 0000664 0000000 0000000 00000022706 14232154237 0021440 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the name of the source blob or file.
// Beginning with version 2012-02-12, this value may be a URL of up to 2 KB in length that specifies a blob.
// The value should be URL-encoded as it would appear in a request URI.
// A source blob in the same storage account can be authenticated via Shared Key.
// However, if the source is a blob in another account,
// the source blob must either be public or must be authenticated via a shared access signature.
// If the source blob is public, no authentication is required to perform the copy operation.
//
// Beginning with version 2015-02-21, the source object may be a file in the Azure File service.
// If the source object is a file that is to be copied to a blob, then the source file must be authenticated
// using a shared access signature, whether it resides in the same account or in a different account.
//
// Only storage accounts created on or after June 7th, 2012 allow the Copy Blob operation to
// copy from another storage account.
CopySource string
// The ID of the Lease
// Required if the destination blob has an active lease.
// The lease ID specified for this header must match the lease ID of the destination blob.
// If the request does not include the lease ID or it is not valid,
// the operation fails with status code 412 (Precondition Failed).
//
// If this header is specified and the destination blob does not currently have an active lease,
// the operation will also fail with status code 412 (Precondition Failed).
LeaseID *string
// The ID of the Lease on the Source Blob
// Specify to perform the Copy Blob operation only if the lease ID matches the active lease ID of the source blob.
SourceLeaseID *string
// For page blobs on a premium account only. Specifies the tier to be set on the target blob
AccessTier *AccessTier
// 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.
MetaData map[string]string
// An ETag value.
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value matches the ETag value for an existing destination blob.
// If the ETag for the destination blob does not match the ETag specified for If-Match,
// the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value, or the wildcard character (*).
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value does not match the ETag value for the destination blob.
// Specify the wildcard character (*) to perform the operation only if the destination blob does not exist.
// If the specified condition isn't met, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has been modified since the specified date/time.
// If the destination blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has not been modified since the specified date/time.
// If the destination blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value.
// Specify this conditional header to copy the source blob only if its ETag matches the value specified.
// If the ETag values do not match, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfMatch *string
// An ETag value.
// Specify this conditional header to copy the blob only if its ETag does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has been modified
// since the specified date/time.
// If the source blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has not been modified
// since the specified date/time.
// If the source blob has been modified, the Blob service returns status code 412 (Precondition Failed).
// This header cannot be specified if the source is an Azure File.
SourceIfUnmodifiedSince *string
}
type CopyResult struct {
autorest.Response
CopyID string
CopyStatus string
}
// Copy copies a blob to a destination within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
req, err := client.CopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": autorest.Encode("header", input.CopySource),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SourceLeaseID != nil {
headers["x-ms-source-lease-id"] = *input.SourceLeaseID
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.SourceIfMatch != nil {
headers["x-ms-source-if-match"] = *input.SourceIfMatch
}
if input.SourceIfNoneMatch != nil {
headers["x-ms-source-if-none-match"] = *input.SourceIfNoneMatch
}
if input.SourceIfModifiedSince != nil {
headers["x-ms-source-if-modified-since"] = *input.SourceIfModifiedSince
}
if input.SourceIfUnmodifiedSince != nil {
headers["x-ms-source-if-unmodified-since"] = *input.SourceIfUnmodifiedSince
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/copy_abort.go 0000664 0000000 0000000 00000007451 14232154237 0022627 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AbortCopyInput struct {
// The Copy ID which should be aborted
CopyID string
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// AbortCopy aborts a pending Copy Blob operation, and leaves a destination blob with zero length and full metadata.
func (client Client) AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`blobName` cannot be an empty string.")
}
if input.CopyID == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`input.CopyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", input.CopyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/copy_and_wait.go 0000664 0000000 0000000 00000002050 14232154237 0023274 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"time"
)
// CopyAndWait copies a blob to a destination within the storage account and waits for it to finish copying.
func (client Client) CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error {
if _, err := client.Copy(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
for true {
getInput := GetPropertiesInput{
LeaseID: input.LeaseID,
}
getResult, err := client.GetProperties(ctx, accountName, containerName, blobName, getInput)
if err != nil {
return fmt.Errorf("")
}
switch getResult.CopyStatus {
case Aborted:
return fmt.Errorf("Copy was aborted: %s", getResult.CopyStatusDescription)
case Failed:
return fmt.Errorf("Copy failed: %s", getResult.CopyStatusDescription)
case Success:
return nil
case Pending:
time.Sleep(pollingInterval)
continue
}
}
return fmt.Errorf("Unexpected error waiting for the copy to complete")
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/copy_test.go 0000664 0000000 0000000 00000012644 14232154237 0022477 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCopyFromExistingFile(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
copiedFileName := "copied.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Duplicating that file..")
copiedInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetBlobEndpoint(blobClient.BaseURI, accountName), containerName, fileName),
}
if err := blobClient.CopyAndWait(ctx, accountName, containerName, copiedFileName, copiedInput, refreshInterval); err != nil {
t.Fatalf("Error duplicating file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Original File..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the original file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Copied File..")
copiedProps, err := blobClient.GetProperties(ctx, accountName, containerName, copiedFileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the copied file: %s", err)
}
if props.ContentLength != copiedProps.ContentLength {
t.Fatalf("Expected the content length to be %d but it was %d", props.ContentLength, copiedProps.ContentLength)
}
t.Logf("[DEBUG] Deleting copied file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, copiedFileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
t.Logf("[DEBUG] Deleting original file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
func TestCopyFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
if props.ContentLength == 0 {
t.Fatalf("Expected the file to be there but looks like it isn't: %d", props.ContentLength)
}
t.Logf("[DEBUG] Deleting file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/delete.go 0000664 0000000 0000000 00000007057 14232154237 0021732 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteInput struct {
// Should any Snapshots for this Blob also be deleted?
// If the Blob has Snapshots and this is set to False a 409 Conflict will be returned
DeleteSnapshots bool
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// Delete marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`blobName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.DeleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/delete_snapshot.go 0000664 0000000 0000000 00000007675 14232154237 0023657 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The DateTime of the Snapshot which should be marked for Deletion
SnapshotDateTime string
}
// DeleteSnapshot marks a single Snapshot of a Blob for Deletion based on it's DateTime, which will be deleted during the next Garbage Collection cycle.
func (client Client) DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`blobName` cannot be an empty string.")
}
if input.SnapshotDateTime == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`input.SnapshotDateTime` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotDateTime),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/delete_snapshots.go 0000664 0000000 0000000 00000007161 14232154237 0024030 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotsInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// DeleteSnapshots marks all Snapshots of a Blob for Deletion, which will be deleted during the next Garbage Collection Cycle.
func (client Client) DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`blobName` cannot be an empty string.")
}
req, err := client.DeleteSnapshotsPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotsPreparer prepares the DeleteSnapshots request.
func (client Client) DeleteSnapshotsPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// only delete the snapshots but leave the blob as-is
"x-ms-delete-snapshots": "only",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotsSender sends the DeleteSnapshots request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotsResponder handles the response to the DeleteSnapshots request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/get.go 0000664 0000000 0000000 00000007611 14232154237 0021243 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetResult struct {
autorest.Response
Contents []byte
}
// Get reads or downloads a blob from the system, including its metadata and properties.
func (client Client) Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Get", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Get", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Get", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Get", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "Get", "`input.LeaseID` should either be specified or nil, not an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "Get", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, containerName, blobName string, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && int(resp.ContentLength) > 0 {
result.Contents = make([]byte, resp.ContentLength)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/get_block_list.go 0000664 0000000 0000000 00000010765 14232154237 0023454 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetBlockListInput struct {
BlockListType BlockListType
LeaseID *string
}
type GetBlockListResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
// A list of blocks which have been committed
CommittedBlocks CommittedBlocks `xml:"CommittedBlocks,omitempty"`
// A list of blocks which have not yet been committed
UncommittedBlocks UncommittedBlocks `xml:"UncommittedBlocks,omitempty"`
}
// GetBlockList retrieves the list of blocks that have been uploaded as part of a block blob.
func (client Client) GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.GetBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", nil, "Failure preparing request")
return
}
resp, err := client.GetBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure sending request")
return
}
result, err = client.GetBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure responding to request")
return
}
return
}
// GetBlockListPreparer prepares the GetBlockList request.
func (client Client) GetBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"blocklisttype": autorest.Encode("query", string(input.BlockListType)),
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetBlockListSender sends the GetBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetBlockListResponder handles the response to the GetBlockList request. The method always
// closes the http.Response Body.
func (client Client) GetBlockListResponder(resp *http.Response) (result GetBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/get_page_ranges.go 0000664 0000000 0000000 00000011500 14232154237 0023566 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPageRangesInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetPageRangesResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
PageRanges []PageRange `xml:"PageRange"`
}
type PageRange struct {
// The start byte offset for this range, inclusive
Start int64 `xml:"Start"`
// The end byte offset for this range, inclusive
End int64 `xml:"End"`
}
// GetPageRanges returns the list of valid page ranges for a page blob or snapshot of a page blob.
func (client Client) GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`blobName` cannot be an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPageRangesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", nil, "Failure preparing request")
return
}
resp, err := client.GetPageRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure sending request")
return
}
result, err = client.GetPageRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure responding to request")
return
}
return
}
// GetPageRangesPreparer prepares the GetPageRanges request.
func (client Client) GetPageRangesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "pagelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPageRangesSender sends the GetPageRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPageRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPageRangesResponder handles the response to the GetPageRanges request. The method always
// closes the http.Response Body.
func (client Client) GetPageRangesResponder(resp *http.Response) (result GetPageRangesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/incremental_copy_blob.go 0000664 0000000 0000000 00000010703 14232154237 0025011 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type IncrementalCopyBlobInput struct {
CopySource string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
}
// IncrementalCopyBlob 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.
func (client Client) IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`input.CopySource` cannot be an empty string.")
}
req, err := client.IncrementalCopyBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", nil, "Failure preparing request")
return
}
resp, err := client.IncrementalCopyBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure sending request")
return
}
result, err = client.IncrementalCopyBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure responding to request")
return
}
return
}
// IncrementalCopyBlobPreparer prepares the IncrementalCopyBlob request.
func (client Client) IncrementalCopyBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "incrementalcopy"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// IncrementalCopyBlobSender sends the IncrementalCopyBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) IncrementalCopyBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// IncrementalCopyBlobResponder handles the response to the IncrementalCopyBlob request. The method always
// closes the http.Response Body.
func (client Client) IncrementalCopyBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/lease_acquire.go 0000664 0000000 0000000 00000011503 14232154237 0023261 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput struct {
// The ID of the existing Lease, if leased
LeaseID *string
// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires.
// A non-infinite lease can be between 15 and 60 seconds
LeaseDuration int
// The Proposed new ID for the Lease
ProposedLeaseID *string
}
type AcquireLeaseResult struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a blob for write and delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseID` cannot be an empty string, if specified.")
}
if input.ProposedLeaseID != nil && *input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.ProposedLeaseID` cannot be an empty string, if specified.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.ProposedLeaseID != nil {
headers["x-ms-proposed-lease-id"] = *input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResult, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/lease_break.go 0000664 0000000 0000000 00000010614 14232154237 0022716 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks an existing lock on a blob using the LeaseID.
func (client Client) BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/lease_change.go 0000664 0000000 0000000 00000007777 14232154237 0023077 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes an existing lock on a blob for another lock.
func (client Client) ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`blobName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/lease_release.go 0000664 0000000 0000000 00000006720 14232154237 0023255 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases a lock based on the Lease ID.
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/lease_renew.go 0000664 0000000 0000000 00000006555 14232154237 0022763 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
func (client Client) RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/lease_test.go 0000664 0000000 0000000 00000007152 14232154237 0022614 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLeaseLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
defer blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{})
// Test begins here
t.Logf("[DEBUG] Acquiring Lease..")
leaseInput := AcquireLeaseInput{
LeaseDuration: -1,
}
leaseInfo, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Changing Lease..")
changeLeaseInput := ChangeLeaseInput{
ExistingLeaseID: leaseInfo.LeaseID,
ProposedLeaseID: "31f5bb01-cdd9-4166-bcdc-95186076bde0",
}
changeLeaseResult, err := blobClient.ChangeLease(ctx, accountName, containerName, fileName, changeLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
t.Logf("[DEBUG] New Lease ID: %q", changeLeaseResult.LeaseID)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, changeLeaseResult.LeaseID); err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Acquiring a new lease..")
leaseInput = AcquireLeaseInput{
LeaseDuration: 30,
}
leaseInfo, err = blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Renewing lease..")
if _, err := blobClient.RenewLease(ctx, accountName, containerName, fileName, leaseInfo.LeaseID); err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
t.Logf("[DEBUG] Breaking lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseInfo.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/lifecycle_test.go 0000664 0000000 0000000 00000012612 14232154237 0023457 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageBlob = Client{}
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Blob Properties..")
details, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 0 {
t.Fatalf("Expected there to be no items of metadata but got %d", len(details.MetaData))
}
t.Logf("[DEBUG] Checking it's returned in the List API..")
listInput := containers.ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 1 {
t.Fatalf("Expected there to be 1 blob in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Setting MetaData..")
metaDataInput := SetMetaDataInput{
MetaData: map[string]string{
"hello": "there",
},
}
if _, err := blobClient.SetMetaData(ctx, accountName, containerName, fileName, metaDataInput); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 1 {
t.Fatalf("Expected there to be 1 item of metadata but got %d", len(details.MetaData))
}
if details.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", details.MetaData["there"])
}
t.Logf("[DEBUG] Retrieving the Block List..")
getBlockListInput := GetBlockListInput{
BlockListType: All,
}
blockList, err := blobClient.GetBlockList(ctx, accountName, containerName, fileName, getBlockListInput)
if err != nil {
t.Fatalf("Error retrieving Block List: %s", err)
}
// since this is a copy from an existing file, all blocks should be present
if len(blockList.CommittedBlocks.Blocks) == 0 {
t.Fatalf("Expected there to be committed blocks but there weren't!")
}
if len(blockList.UncommittedBlocks.Blocks) != 0 {
t.Fatalf("Expected all blocks to be committed but got %d uncommitted blocks", len(blockList.UncommittedBlocks.Blocks))
}
t.Logf("[DEBUG] Changing the Access Tiers..")
tiers := []AccessTier{
Hot,
Cool,
Archive,
}
for _, tier := range tiers {
t.Logf("[DEBUG] Updating the Access Tier to %q..", string(tier))
if _, err := blobClient.SetTier(ctx, accountName, containerName, fileName, tier); err != nil {
t.Fatalf("Error setting the Access Tier: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
if details.AccessTier != tier {
t.Fatalf("Expected the AccessTier to be %q but got %q", tier, details.AccessTier)
}
}
t.Logf("[DEBUG] Deleting Blob")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/metadata_set.go 0000664 0000000 0000000 00000007724 14232154237 0023124 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SetMetaDataInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// Any metadata which should be added to this blob
MetaData map[string]string
}
// SetMetaData marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "GetProperties", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/models.go 0000664 0000000 0000000 00000002714 14232154237 0021746 0 ustar 00root root 0000000 0000000 package blobs
type AccessTier string
var (
Archive AccessTier = "Archive"
Cool AccessTier = "Cool"
Hot AccessTier = "Hot"
)
type ArchiveStatus string
var (
None ArchiveStatus = ""
RehydratePendingToCool ArchiveStatus = "rehydrate-pending-to-cool"
RehydratePendingToHot ArchiveStatus = "rehydrate-pending-to-hot"
)
type BlockListType string
var (
All BlockListType = "all"
Committed BlockListType = "committed"
Uncommitted BlockListType = "uncommitted"
)
type Block struct {
// The base64-encoded Block ID
Name string `xml:"Name"`
// The size of the Block in Bytes
Size int64 `xml:"Size"`
}
type BlobType string
var (
AppendBlob BlobType = "AppendBlob"
BlockBlob BlobType = "BlockBlob"
PageBlob BlobType = "PageBlob"
)
type CommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
type CopyStatus string
var (
Aborted CopyStatus = "aborted"
Failed CopyStatus = "failed"
Pending CopyStatus = "pending"
Success CopyStatus = "success"
)
type LeaseDuration string
var (
Fixed LeaseDuration = "fixed"
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
type UncommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/properties_get.go 0000664 0000000 0000000 00000031314 14232154237 0023514 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
type GetPropertiesResult struct {
autorest.Response
// The tier of page blob on a premium storage account or tier of block blob on blob storage or general purpose v2 account.
AccessTier AccessTier
// This gives the last time tier was changed on the object.
// This header is returned only if tier on block blob was ever set.
// The date format follows RFC 1123
AccessTierChangeTime string
// For page blobs on a premium storage account only.
// If the access tier is not explicitly set on the blob, the tier is inferred based on its content length
// and this header will be returned with true value.
// For block blobs on Blob Storage or general purpose v2 account, if the blob does not have the access tier
// set then we infer the tier from the storage account properties. This header is set only if the block blob
// tier is inferred
AccessTierInferred bool
// For blob storage or general purpose v2 account.
// If the blob is being rehydrated and is not complete then this header is returned indicating
// that rehydrate is pending and also tells the destination tier
ArchiveStatus ArchiveStatus
// The number of committed blocks present in the blob.
// This header is returned only for append blobs.
BlobCommittedBlockCount string
// The current sequence number for a page blob.
// This header is not returned for block blobs or append blobs.
// This header is not returned for block blobs.
BlobSequenceNumber string
// The blob type.
BlobType BlobType
// If the Cache-Control request header has previously been set for the blob, that value is returned in this header.
CacheControl string
// The Content-Disposition response header field conveys additional information about how to process
// the response payload, and also can be used to attach additional metadata.
// For example, if set to attachment, it indicates that the user-agent should not display the response,
// but instead show a Save As dialog.
ContentDisposition string
// If the Content-Encoding request header has previously been set for the blob,
// that value is returned in this header.
ContentEncoding string
// If the Content-Language request header has previously been set for the blob,
// that value is returned in this header.
ContentLanguage string
// The size of the blob in bytes.
// For a page blob, this header returns the value of the x-ms-blob-content-length header stored with the blob.
ContentLength int64
// The content type specified for the blob.
// If no content type was specified, the default content type is `application/octet-stream`.
ContentType string
// If the Content-MD5 header has been set for the blob, this response header is returned so that
// the client can check for message content integrity.
ContentMD5 string
// Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob.
// This value can specify the time of a completed, aborted, or failed copy attempt.
// This header does not appear if a copy is pending, if this blob has never been the
// destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob
// operation using Set Blob Properties, Put Blob, or Put Block List.
CopyCompletionTime string
// Included if the blob is incremental copy blob or incremental copy snapshot, if x-ms-copy-status is success.
// Snapshot time of the last successful incremental copy snapshot for this blob
CopyDestinationSnapshot string
// String identifier for the last attempted Copy Blob operation where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyID string
// Contains the number of bytes copied and the total bytes in the source in the last attempted
// Copy Blob operation where this blob was the destination blob.
// Can show between 0 and Content-Length bytes copied.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyProgress string
// URL up to 2 KB in length that specifies the source blob used in the last attempted Copy Blob operation
// where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List
CopySource string
// State of the copy operation identified by x-ms-copy-id, with these values:
// - success: Copy completed successfully.
// - pending: Copy is in progress.
// Check x-ms-copy-status-description if intermittent, non-fatal errors
// impede copy progress but don’t cause failure.
// - aborted: Copy was ended by Abort Copy Blob.
// - failed: Copy failed. See x-ms- copy-status-description for failure details.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a completed Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatus CopyStatus
// Describes cause of fatal or non-fatal copy operation failure.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatusDescription string
// The date/time at which the blob was created. The date format follows RFC 1123
CreationTime string
// The ETag contains a value that you can use to perform operations conditionally
ETag string
// Included if the blob is incremental copy blob.
IncrementalCopy bool
// The date/time that the blob was last modified. The date format follows RFC 1123.
LastModified string
// When a blob is leased, specifies whether the lease is of infinite or fixed duration
LeaseDuration LeaseDuration
// The lease state of the blob
LeaseState LeaseState
LeaseStatus LeaseStatus
// A set of name-value pairs that correspond to the user-defined metadata associated with this blob
MetaData map[string]string
// Is the Storage Account encrypted using server-side encryption? This should always return true
ServerEncrypted bool
}
// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the blob
func (client Client) GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.AccessTier = AccessTier(resp.Header.Get("x-ms-access-tier"))
result.AccessTierChangeTime = resp.Header.Get(" x-ms-access-tier-change-time")
result.ArchiveStatus = ArchiveStatus(resp.Header.Get(" x-ms-archive-status"))
result.BlobCommittedBlockCount = resp.Header.Get("x-ms-blob-committed-block-count")
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.BlobType = BlobType(resp.Header.Get("x-ms-blob-type"))
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.CopyDestinationSnapshot = resp.Header.Get("x-ms-copy-destination-snapshot")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = CopyStatus(resp.Header.Get("x-ms-copy-status"))
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CreationTime = resp.Header.Get("x-ms-creation-time")
result.ETag = resp.Header.Get("Etag")
result.LastModified = resp.Header.Get("Last-Modified")
result.LeaseDuration = LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.MetaData = metadata.ParseFromHeaders(resp.Header)
if v := resp.Header.Get("x-ms-access-tier-inferred"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.AccessTierInferred = b
}
if v := resp.Header.Get("Content-Length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
}
result.ContentLength = int64(i)
}
if v := resp.Header.Get("x-ms-incremental-copy"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
if v := resp.Header.Get("x-ms-server-encrypted"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/properties_set.go 0000664 0000000 0000000 00000012111 14232154237 0023522 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
CacheControl *string
ContentType *string
ContentMD5 *string
ContentEncoding *string
ContentLanguage *string
LeaseID *string
ContentDisposition *string
ContentLength *int64
SequenceNumberAction *SequenceNumberAction
BlobSequenceNumber *string
}
type SetPropertiesResult struct {
autorest.Response
BlobSequenceNumber string
Etag string
}
// SetProperties sets system properties on the blob.
func (client Client) SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
type SequenceNumberAction string
var (
Increment SequenceNumberAction = "increment"
Max SequenceNumberAction = "max"
Update SequenceNumberAction = "update"
)
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.ContentLength != nil {
headers["x-ms-blob-content-length"] = *input.ContentLength
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SequenceNumberAction != nil {
headers["x-ms-sequence-number-action"] = string(*input.SequenceNumberAction)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result SetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.Etag = resp.Header.Get("Etag")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_append_blob.go 0000664 0000000 0000000 00000011323 14232154237 0023614 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutAppendBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutAppendBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new append blob, or updates the content of an existing blob.
func (client Client) PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutAppendBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutAppendBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutAppendBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure sending request")
return
}
result, err = client.PutAppendBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure responding to request")
return
}
return
}
// PutAppendBlobPreparer prepares the PutAppendBlob request.
func (client Client) PutAppendBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(AppendBlob),
"x-ms-version": APIVersion,
// For a page blob or an append blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutAppendBlobSender sends the PutAppendBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutAppendBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutAppendBlobResponder handles the response to the PutAppendBlob request. The method always
// closes the http.Response Body.
func (client Client) PutAppendBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_block.go 0000664 0000000 0000000 00000010100 14232154237 0022431 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockInput struct {
BlockID string
Content []byte
ContentMD5 *string
LeaseID *string
}
type PutBlockResult struct {
autorest.Response
ContentMD5 string
}
// PutBlock creates a new block to be committed as part of a blob.
func (client Client) PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.BlockID` cannot be an empty string.")
}
if len(input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.Content` cannot be empty.")
}
req, err := client.PutBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure sending request")
return
}
result, err = client.PutBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure responding to request")
return
}
return
}
// PutBlockPreparer prepares the PutBlock request.
func (client Client) PutBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Content-Length": int(len(input.Content)),
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockSender sends the PutBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockResponder handles the response to the PutBlock request. The method always
// closes the http.Response Body.
func (client Client) PutBlockResponder(resp *http.Response) (result PutBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_block_blob.go 0000664 0000000 0000000 00000011750 14232154237 0023443 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutBlockBlobInput struct {
CacheControl *string
Content *[]byte
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutBlockBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block append blob, or updates the content of an existing block blob.
func (client Client) PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`input.Content` must either be nil or not empty.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutBlockBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutBlockBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure sending request")
return
}
result, err = client.PutBlockBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure responding to request")
return
}
return
}
// PutBlockBlobPreparer prepares the PutBlockBlob request.
func (client Client) PutBlockBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(BlockBlob),
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockBlobSender sends the PutBlockBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockBlobResponder handles the response to the PutBlockBlob request. The method always
// closes the http.Response Body.
func (client Client) PutBlockBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_block_blob_file.go 0000664 0000000 0000000 00000001510 14232154237 0024433 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"io"
"os"
)
// PutBlockBlobFromFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
bytes := make([]byte, fileSize)
_, err = file.ReadAt(bytes, 0)
if err != nil {
if err != io.EOF {
return fmt.Errorf("Error reading bytes: %s", err)
}
}
input.Content = &bytes
if _, err = client.PutBlockBlob(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error putting bytes: %s", err)
}
return nil
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_block_list.go 0000664 0000000 0000000 00000012220 14232154237 0023471 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type BlockList struct {
CommittedBlockIDs []BlockID `xml:"Committed,omitempty"`
UncommittedBlockIDs []BlockID `xml:"Uncommitted,omitempty"`
LatestBlockIDs []BlockID `xml:"Latest,omitempty"`
}
type BlockID struct {
Value string `xml:",chardata"`
}
type PutBlockListInput struct {
BlockList BlockList
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
MetaData map[string]string
LeaseID *string
}
type PutBlockListResult struct {
autorest.Response
ContentMD5 string
ETag string
LastModified string
}
// PutBlockList 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.
func (client Client) PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.PutBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure sending request")
return
}
result, err = client.PutBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure responding to request")
return
}
return
}
// PutBlockListPreparer prepares the PutBlockList request.
func (client Client) PutBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(input.BlockList))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockListSender sends the PutBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockListResponder handles the response to the PutBlockList request. The method always
// closes the http.Response Body.
func (client Client) PutBlockListResponder(resp *http.Response) (result PutBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_block_url.go 0000664 0000000 0000000 00000010564 14232154237 0023331 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockFromURLInput struct {
BlockID string
CopySource string
ContentMD5 *string
LeaseID *string
Range *string
}
type PutBlockFromURLResult struct {
autorest.Response
ContentMD5 string
}
// PutBlockFromURL creates a new block to be committed as part of a blob where the contents are read from a URL
func (client Client) PutBlockFromURL(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (result PutBlockFromURLResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.BlockID` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.CopySource` cannot be an empty string.")
}
req, err := client.PutBlockFromURLPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockFromURLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure sending request")
return
}
result, err = client.PutBlockFromURLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure responding to request")
return
}
return
}
// PutBlockFromURLPreparer prepares the PutBlockFromURL request.
func (client Client) PutBlockFromURLPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.ContentMD5 != nil {
headers["x-ms-source-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Range != nil {
headers["x-ms-source-range"] = *input.Range
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockFromURLSender sends the PutBlockFromURL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockFromURLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockFromURLResponder handles the response to the PutBlockFromURL request. The method always
// closes the http.Response Body.
func (client Client) PutBlockFromURLResponder(resp *http.Response) (result PutBlockFromURLResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_page_blob.go 0000664 0000000 0000000 00000012264 14232154237 0023266 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutPageBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
BlobContentLengthBytes int64
BlobSequenceNumber *int64
AccessTier *AccessTier
}
// PutPageBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block blob, or updates the content of an existing page blob.
func (client Client) PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`blobName` cannot be an empty string.")
}
if input.BlobContentLengthBytes == 0 || input.BlobContentLengthBytes%512 != 0 {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`input.BlobContentLengthBytes` must be aligned to a 512-byte boundary.")
}
req, err := client.PutPageBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutPageBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure sending request")
return
}
result, err = client.PutPageBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure responding to request")
return
}
return
}
// PutPageBlobPreparer prepares the PutPageBlob request.
func (client Client) PutPageBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(PageBlob),
"x-ms-version": APIVersion,
// For a page blob or an page blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
// This header specifies the maximum size for the page blob, up to 8 TB.
// The page blob size must be aligned to a 512-byte boundary.
"x-ms-blob-content-length": input.BlobContentLengthBytes,
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageBlobSender sends the PutPageBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageBlobResponder handles the response to the PutPageBlob request. The method always
// closes the http.Response Body.
func (client Client) PutPageBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_page_clear.go 0000664 0000000 0000000 00000007556 14232154237 0023446 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageClearInput struct {
StartByte int64
EndByte int64
LeaseID *string
}
// PutPageClear clears a range of pages within a page blob.
func (client Client) PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.EndByte` must be greater than 0.")
}
req, err := client.PutPageClearPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", nil, "Failure preparing request")
return
}
resp, err := client.PutPageClearSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure sending request")
return
}
result, err = client.PutPageClearResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure responding to request")
return
}
return
}
// PutPageClearPreparer prepares the PutPageClear request.
func (client Client) PutPageClearPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageClearSender sends the PutPageClear request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageClearSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageClearResponder handles the response to the PutPageClear request. The method always
// closes the http.Response Body.
func (client Client) PutPageClearResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/put_page_update.go 0000664 0000000 0000000 00000012777 14232154237 0023643 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageUpdateInput struct {
StartByte int64
EndByte int64
Content []byte
IfSequenceNumberEQ *string
IfSequenceNumberLE *string
IfSequenceNumberLT *string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
LeaseID *string
}
type PutPageUpdateResult struct {
autorest.Response
BlobSequenceNumber string
ContentMD5 string
LastModified string
}
// PutPageUpdate writes a range of pages to a page blob.
func (client Client) PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.EndByte` must be greater than 0.")
}
expectedSize := (input.EndByte - input.StartByte) + 1
actualSize := int64(len(input.Content))
if expectedSize != actualSize {
return result, validation.NewError("blobs.Client", "PutPageUpdate", fmt.Sprintf("Content Size was defined as %d but got %d.", expectedSize, actualSize))
}
req, err := client.PutPageUpdatePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", nil, "Failure preparing request")
return
}
resp, err := client.PutPageUpdateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure sending request")
return
}
result, err = client.PutPageUpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure responding to request")
return
}
return
}
// PutPageUpdatePreparer prepares the PutPageUpdate request.
func (client Client) PutPageUpdatePreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
"Content-Length": int(len(input.Content)),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfSequenceNumberEQ != nil {
headers["x-ms-if-sequence-number-eq"] = *input.IfSequenceNumberEQ
}
if input.IfSequenceNumberLE != nil {
headers["x-ms-if-sequence-number-le"] = *input.IfSequenceNumberLE
}
if input.IfSequenceNumberLT != nil {
headers["x-ms-if-sequence-number-lt"] = *input.IfSequenceNumberLT
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageUpdateSender sends the PutPageUpdate request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageUpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageUpdateResponder handles the response to the PutPageUpdate request. The method always
// closes the http.Response Body.
func (client Client) PutPageUpdateResponder(resp *http.Response) (result PutPageUpdateResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/resource_id.go 0000664 0000000 0000000 00000003060 14232154237 0022761 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Blob
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName, blobName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, containerName, blobName)
}
type ResourceID struct {
AccountName string
ContainerName string
BlobName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Blob Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar/example.vhd
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
containerName := segments[0]
blobName := strings.TrimPrefix(path, containerName)
blobName = strings.TrimPrefix(blobName, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
BlobName: blobName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/resource_id_test.go 0000664 0000000 0000000 00000006670 14232154237 0024032 0 ustar 00root root 0000000 0000000 package blobs
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1", "blob1.vhd")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "blob1.vhd" {
t.Fatalf("Expected Blob Name to be `blob1.vhd` but got %q", actual.BlobName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/example/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/example/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/example/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/example/blob1.vhd",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "example/blob1.vhd" {
t.Fatalf("Expected Blob Name to be `example/blob1.vhd` but got %q", actual.BlobName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/set_tier.go 0000664 0000000 0000000 00000006325 14232154237 0022303 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetTier sets the tier on a blob.
func (client Client) SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`blobName` cannot be an empty string.")
}
req, err := client.SetTierPreparer(ctx, accountName, containerName, blobName, tier)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", nil, "Failure preparing request")
return
}
resp, err := client.SetTierSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure sending request")
return
}
result, err = client.SetTierResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure responding to request")
return
}
return
}
// SetTierPreparer prepares the SetTier request.
func (client Client) SetTierPreparer(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "tier"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-access-tier": string(tier),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetTierSender sends the SetTier request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetTierSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetTierResponder handles the response to the SetTier request. The method always
// closes the http.Response Body.
func (client Client) SetTierResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/snapshot.go 0000664 0000000 0000000 00000013463 14232154237 0022325 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// MetaData is a user-defined name-value pair associated with the blob.
// If no name-value pairs are specified, the operation will copy the base blob metadata to the snapshot.
// If one or more name-value pairs are specified, the snapshot is created with the specified metadata,
// and metadata is not copied from the base blob.
MetaData map[string]string
// A DateTime value which will only snapshot the blob if it has been modified since the specified date/time
// If the base blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value which will only snapshot the blob if it has not been modified since the specified date/time
// If the base blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value to snapshot the blob only if its ETag value matches the value specified.
// If the values do not match, the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value for this conditional header to snapshot the blob only if its ETag value
// does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
}
type SnapshotResult struct {
autorest.Response
// The ETag of the snapshot
ETag string
// A DateTime value that uniquely identifies the snapshot.
// The value of this header indicates the snapshot version,
// and may be used in subsequent requests to access the snapshot.
SnapshotDateTime string
}
// Snapshot captures a Snapshot of a given Blob
func (client Client) Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "Snapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", nil, "Failure preparing request")
return
}
resp, err := client.SnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure sending request")
return
}
result, err = client.SnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure responding to request")
return
}
return
}
// SnapshotPreparer prepares the Snapshot request.
func (client Client) SnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SnapshotSender sends the Snapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SnapshotResponder handles the response to the Snapshot request. The method always
// closes the http.Response Body.
func (client Client) SnapshotResponder(resp *http.Response) (result SnapshotResult, err error) {
if resp != nil && resp.Header != nil {
result.ETag = resp.Header.Get("ETag")
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/snapshot_get_properties.go 0000664 0000000 0000000 00000006445 14232154237 0025442 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetSnapshotPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The ID of the Snapshot which should be retrieved
SnapshotID string
}
// GetSnapshotProperties returns all user-defined metadata, standard HTTP properties, and system properties for
// the specified snapshot of a blob
func (client Client) GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`blobName` cannot be an empty string.")
}
if input.SnapshotID == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`input.SnapshotID` cannot be an empty string.")
}
req, err := client.GetSnapshotPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", nil, "Failure preparing request")
return
}
// we re-use the GetProperties methods since this is otherwise the same
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/snapshot_test.go 0000664 0000000 0000000 00000013411 14232154237 0023355 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestSnapshotLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatalf("Error creating: %s", err)
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] First Snapshot..")
firstSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{})
if err != nil {
t.Fatalf("Error taking first snapshot: %s", err)
}
t.Logf("[DEBUG] First Snapshot ID: %q", firstSnapshot.SnapshotDateTime)
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
t.Logf("[DEBUG] Second Snapshot..")
secondSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
MetaData: map[string]string{
"hello": "world",
},
})
if err != nil {
t.Fatalf("Error taking Second snapshot: %s", err)
}
t.Logf("[DEBUG] Second Snapshot ID: %q", secondSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Leasing the Blob..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
// infinite
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error leasing Blob: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Third Snapshot..")
thirdSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error taking Third snapshot: %s", err)
}
t.Logf("[DEBUG] Third Snapshot ID: %q", thirdSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, leaseDetails.LeaseID); err != nil {
t.Fatalf("Error releasing Lease: %s", err)
}
// get the properties from the blob, which should include the LastModifiedDate
t.Logf("[DEBUG] Retrieving Properties for Blob")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
// confirm that the If-Modified-None returns an error
t.Logf("[DEBUG] Third Snapshot..")
fourthSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
IfModifiedSince: &props.LastModified,
})
if err == nil {
t.Fatalf("Expected an error but didn't get one")
}
if fourthSnapshot.Response.StatusCode != http.StatusPreconditionFailed {
t.Fatalf("Expected the status code to be Precondition Failed but got: %d", fourthSnapshot.Response.StatusCode)
}
t.Logf("[DEBUG] Retrieving the Second Snapshot Properties..")
getSecondSnapshotInput := GetSnapshotPropertiesInput{
SnapshotID: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput); err != nil {
t.Fatalf("Error retrieving properties for the second snapshot: %s", err)
}
t.Logf("[DEBUG] Deleting the Second Snapshot..")
deleteSnapshotInput := DeleteSnapshotInput{
SnapshotDateTime: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.DeleteSnapshot(ctx, accountName, containerName, fileName, deleteSnapshotInput); err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Second Snapshot Properties..")
secondSnapshotProps, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput)
if err == nil {
t.Fatalf("Expected an error retrieving the snapshot but got none")
}
if secondSnapshotProps.Response.StatusCode != http.StatusNotFound {
t.Fatalf("Expected the status code to be %d but got %q", http.StatusNoContent, secondSnapshotProps.Response.StatusCode)
}
t.Logf("[DEBUG] Deleting all the snapshots..")
if _, err := blobClient.DeleteSnapshots(ctx, accountName, containerName, fileName, DeleteSnapshotsInput{}); err != nil {
t.Fatalf("Error deleting snapshots: %s", err)
}
t.Logf("[DEBUG] Deleting the Blob..")
deleteInput := DeleteInput{
DeleteSnapshots: false,
}
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, deleteInput); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/undelete.go 0000664 0000000 0000000 00000006323 14232154237 0022270 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Undelete restores the contents and metadata of soft deleted blob and any associated soft deleted snapshots.
func (client Client) Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`blobName` cannot be an empty string.")
}
req, err := client.UndeletePreparer(ctx, accountName, containerName, blobName)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", nil, "Failure preparing request")
return
}
resp, err := client.UndeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure sending request")
return
}
result, err = client.UndeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure responding to request")
return
}
return
}
// UndeletePreparer prepares the Undelete request.
func (client Client) UndeletePreparer(ctx context.Context, accountName, containerName, blobName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "undelete"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UndeleteSender sends the Undelete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UndeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UndeleteResponder handles the response to the Undelete request. The method always
// closes the http.Response Body.
func (client Client) UndeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/blobs/version.go 0000664 0000000 0000000 00000000463 14232154237 0022147 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/ 0000775 0000000 0000000 00000000000 14232154237 0021174 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/blob/containers/README.md 0000664 0000000 0000000 00000002257 14232154237 0022461 0 ustar 00root root 0000000 0000000 ## Blob Storage Container SDK for API version 2018-11-09
This package allows you to interact with the Containers Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
Note: when using the `ListBlobs` operation, only `SharedKeyLite` authentication is supported.
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
containersClient := containers.New()
containersClient.Client.Authorizer = storageAuth
ctx := context.TODO()
createInput := containers.CreateInput{
AccessLevel: containers.Private,
}
if _, err := containersClient.Create(ctx, accountName, containerName, createInput); err != nil {
return fmt.Errorf("Error creating Container: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/blob/containers/api.go 0000664 0000000 0000000 00000003675 14232154237 0022307 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageContainer interface {
Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error)
Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error)
GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error)
GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error)
AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error)
BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error)
ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error)
ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error)
RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error)
ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error)
GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, containerName string) string
SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error)
SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error)
SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error)
SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/client.go 0000664 0000000 0000000 00000001632 14232154237 0023003 0 ustar 00root root 0000000 0000000 package containers
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Containers.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
func (client Client) setAccessLevelIntoHeaders(headers map[string]interface{}, level AccessLevel) map[string]interface{} {
// If this header is not included in the request, container data is private to the account owner.
if level != Private {
headers["x-ms-blob-public-access"] = string(level)
}
return headers
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/create.go 0000664 0000000 0000000 00000010233 14232154237 0022765 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies whether data in the container may be accessed publicly and the level of access
AccessLevel AccessLevel
// A name-value pair to associate with the container as metadata.
MetaData map[string]string
}
type CreateResponse struct {
autorest.Response
Error *ErrorResponse `xml:"Error"`
}
// Create creates a new container under the specified account.
// If the container with the same name already exists, the operation fails.
func (client Client) Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Create", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Create", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("containers.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, containerName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, input.AccessLevel)
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result CreateResponse, err error) {
successfulStatusCodes := []int{
http.StatusCreated,
}
if autorest.ResponseHasStatusCode(resp, successfulStatusCodes...) {
// when successful there's no response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
} else {
// however when there's an error the error's in the response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/delete.go 0000664 0000000 0000000 00000005600 14232154237 0022766 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete marks the specified container for deletion.
// The container and any blobs contained within it are later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Delete", "`containerName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, containerName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/get_properties.go 0000664 0000000 0000000 00000011677 14232154237 0024572 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// GetProperties returns the properties for this Container without a Lease
func (client Client) GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error) {
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
return client.GetPropertiesWithLeaseID(ctx, accountName, containerName, "")
}
// GetPropertiesWithLeaseID returns the properties for this Container using the specified LeaseID
func (client Client) GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`containerName` cannot be an empty string.")
}
req, err := client.GetPropertiesWithLeaseIDPreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesWithLeaseIDSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesWithLeaseIDPreparer prepares the GetPropertiesWithLeaseID request.
func (client Client) GetPropertiesWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesWithLeaseIDSender sends the GetPropertiesWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesWithLeaseIDResponder handles the response to the GetPropertiesWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesWithLeaseIDResponder(resp *http.Response) (result ContainerProperties, err error) {
if resp != nil {
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
if result.LeaseStatus == Locked {
duration := LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseDuration = &duration
}
// If this header is not returned in the response, the container is private to the account owner.
accessLevel := resp.Header.Get("x-ms-blob-public-access")
if accessLevel != "" {
result.AccessLevel = AccessLevel(accessLevel)
} else {
result.AccessLevel = Private
}
// we can't necessarily use strconv.ParseBool here since this could be nil (only in some API versions)
result.HasImmutabilityPolicy = strings.EqualFold(resp.Header.Get("x-ms-has-immutability-policy"), "true")
result.HasLegalHold = strings.EqualFold(resp.Header.Get("x-ms-has-legal-hold"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/lease_acquire.go 0000664 0000000 0000000 00000007762 14232154237 0024341 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput 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
LeaseDuration int
ProposedLeaseID string
}
type AcquireLeaseResponse struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a container for delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("containers.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName string, containerName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.ProposedLeaseID != "" {
headers["x-ms-proposed-lease-id"] = input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/lease_break.go 0000664 0000000 0000000 00000010521 14232154237 0023757 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strconv"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks a lock based on it's Lease ID
func (client Client) BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName string, containerName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result BreakLeaseResponse, err error) {
if resp != nil {
leaseRaw := resp.Header.Get("x-ms-lease-time")
if leaseRaw != "" {
i, err := strconv.Atoi(leaseRaw)
if err == nil {
result.LeaseTime = i
}
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/lease_change.go 0000664 0000000 0000000 00000007356 14232154237 0024134 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes the lock from one Lease ID to another Lease ID
func (client Client) ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName string, containerName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/lease_release.go 0000664 0000000 0000000 00000006324 14232154237 0024321 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases the lock based on the Lease ID
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/lease_renew.go 0000664 0000000 0000000 00000006250 14232154237 0024017 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// RenewLease renews the lock based on the Lease ID
func (client Client) RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/lifecycle_test.go 0000664 0000000 0000000 00000013122 14232154237 0024520 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageContainer = Client{}
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
// first let's test an empty container
input := CreateInput{}
_, err = containersClient.Create(ctx, accountName, containerName, input)
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
container, err := containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error retrieving: %s", err))
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if len(container.MetaData) != 0 {
t.Fatalf("Expected MetaData to be empty but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the metadata
metaData := map[string]string{
"dont": "kill-my-vibe",
}
_, err = containersClient.SetMetaData(ctx, accountName, containerName, metaData)
if err != nil {
t.Fatal(fmt.Errorf("Error updating metadata: %s", err))
}
// give azure time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.MetaData["dont"] != "kill-my-vibe" {
t.Fatalf("Expected `kill-my-vibe` but got %q", container.MetaData["dont"])
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the ACL
_, err = containersClient.SetAccessControl(ctx, accountName, containerName, Blob)
if err != nil {
t.Fatal(fmt.Errorf("Error updating ACL's: %s", err))
}
// give azure some time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if container.AccessLevel != Blob {
t.Fatalf("Expected Access Level to be Blob but got %q", container.AccessLevel)
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// acquire a lease for 30s
acquireLeaseInput := AcquireLeaseInput{
LeaseDuration: 30,
}
acquireLeaseResp, err := containersClient.AcquireLease(ctx, accountName, containerName, acquireLeaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %s", acquireLeaseResp.LeaseID)
// we should then be able to update the ID
t.Logf("[DEBUG] Changing lease..")
updateLeaseInput := ChangeLeaseInput{
ExistingLeaseID: acquireLeaseResp.LeaseID,
ProposedLeaseID: "aaaabbbb-aaaa-bbbb-cccc-aaaabbbbcccc",
}
updateLeaseResp, err := containersClient.ChangeLease(ctx, accountName, containerName, updateLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
// then renew it
_, err = containersClient.RenewLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
// and then give it a timeout
breakPeriod := 20
breakLeaseInput := BreakLeaseInput{
LeaseID: updateLeaseResp.LeaseID,
BreakPeriod: &breakPeriod,
}
breakLeaseResp, err := containersClient.BreakLease(ctx, accountName, containerName, breakLeaseInput)
if err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
if breakLeaseResp.LeaseTime == 0 {
t.Fatalf("Lease broke immediately when should have waited: %d", breakLeaseResp.LeaseTime)
}
// and finally ditch it
_, err = containersClient.ReleaseLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Listing blobs in the container..")
listInput := ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 0 {
t.Fatalf("Expected there to be no blobs in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Deleting..")
_, err = containersClient.Delete(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/list_blobs.go 0000664 0000000 0000000 00000015033 14232154237 0023661 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListBlobsInput struct {
Delimiter *string
Include *[]Dataset
Marker *string
MaxResults *int
Prefix *string
}
type ListBlobsResult struct {
autorest.Response
Delimiter string `xml:"Delimiter"`
Marker string `xml:"Marker"`
MaxResults int `xml:"MaxResults"`
NextMarker *string `xml:"NextMarker,omitempty"`
Prefix string `xml:"Prefix"`
Blobs Blobs `xml:"Blobs"`
}
type Blobs struct {
Blobs []BlobDetails `xml:"Blob"`
BlobPrefix *BlobPrefix `xml:"BlobPrefix"`
}
type BlobDetails struct {
Name string `xml:"Name"`
Deleted bool `xml:"Deleted,omitempty"`
MetaData map[string]interface{} `map:"Metadata,omitempty"`
Properties *BlobProperties `xml:"Properties,omitempty"`
Snapshot *string `xml:"Snapshot,omitempty"`
}
type BlobProperties struct {
AccessTier *string `xml:"AccessTier,omitempty"`
AccessTierInferred *bool `xml:"AccessTierInferred,omitempty"`
AccessTierChangeTime *string `xml:"AccessTierChangeTime,omitempty"`
BlobType *string `xml:"BlobType,omitempty"`
BlobSequenceNumber *string `xml:"x-ms-blob-sequence-number,omitempty"`
CacheControl *string `xml:"Cache-Control,omitempty"`
ContentEncoding *string `xml:"ContentEncoding,omitempty"`
ContentLanguage *string `xml:"Content-Language,omitempty"`
ContentLength *int64 `xml:"Content-Length,omitempty"`
ContentMD5 *string `xml:"Content-MD5,omitempty"`
ContentType *string `xml:"Content-Type,omitempty"`
CopyCompletionTime *string `xml:"CopyCompletionTime,omitempty"`
CopyId *string `xml:"CopyId,omitempty"`
CopyStatus *string `xml:"CopyStatus,omitempty"`
CopySource *string `xml:"CopySource,omitempty"`
CopyProgress *string `xml:"CopyProgress,omitempty"`
CopyStatusDescription *string `xml:"CopyStatusDescription,omitempty"`
CreationTime *string `xml:"CreationTime,omitempty"`
ETag *string `xml:"Etag,omitempty"`
DeletedTime *string `xml:"DeletedTime,omitempty"`
IncrementalCopy *bool `xml:"IncrementalCopy,omitempty"`
LastModified *string `xml:"Last-Modified,omitempty"`
LeaseDuration *string `xml:"LeaseDuration,omitempty"`
LeaseState *string `xml:"LeaseState,omitempty"`
LeaseStatus *string `xml:"LeaseStatus,omitempty"`
RemainingRetentionDays *string `xml:"RemainingRetentionDays,omitempty"`
ServerEncrypted *bool `xml:"ServerEncrypted,omitempty"`
}
type BlobPrefix struct {
Name string `xml:"Name"`
}
// ListBlobs lists the blobs matching the specified query within the specified Container
func (client Client) ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`containerName` cannot be an empty string.")
}
if input.MaxResults != nil && (*input.MaxResults <= 0 || *input.MaxResults > 5000) {
return result, validation.NewError("containers.Client", "ListBlobs", "`input.MaxResults` can either be nil or between 0 and 5000.")
}
req, err := client.ListBlobsPreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", nil, "Failure preparing request")
return
}
resp, err := client.ListBlobsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure sending request")
return
}
result, err = client.ListBlobsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure responding to request")
return
}
return
}
// ListBlobsPreparer prepares the ListBlobs request.
func (client Client) ListBlobsPreparer(ctx context.Context, accountName, containerName string, input ListBlobsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "list"),
"restype": autorest.Encode("query", "container"),
}
if input.Delimiter != nil {
queryParameters["delimiter"] = autorest.Encode("query", *input.Delimiter)
}
if input.Include != nil {
vals := make([]string, 0)
for _, v := range *input.Include {
vals = append(vals, string(v))
}
include := strings.Join(vals, ",")
queryParameters["include"] = autorest.Encode("query", include)
}
if input.Marker != nil {
queryParameters["marker"] = autorest.Encode("query", *input.Marker)
}
if input.MaxResults != nil {
queryParameters["maxresults"] = autorest.Encode("query", *input.MaxResults)
}
if input.Prefix != nil {
queryParameters["prefix"] = autorest.Encode("query", *input.Prefix)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListBlobsSender sends the ListBlobs request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListBlobsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListBlobsResponder handles the response to the ListBlobs request. The method always
// closes the http.Response Body.
func (client Client) ListBlobsResponder(resp *http.Response) (result ListBlobsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/models.go 0000664 0000000 0000000 00000003464 14232154237 0023015 0 ustar 00root root 0000000 0000000 package containers
import "github.com/Azure/go-autorest/autorest"
type AccessLevel string
var (
// Blob specifies public read access for blobs.
// Blob data within this container can be read via anonymous request,
// but container data is not available.
// Clients cannot enumerate blobs within the container via anonymous request.
Blob AccessLevel = "blob"
// Container specifies full public read access for container and blob data.
// Clients can enumerate blobs within the container via anonymous request,
// but cannot enumerate containers within the storage account.
Container AccessLevel = "container"
// Private specifies that container data is private to the account owner
Private AccessLevel = ""
)
type ContainerProperties struct {
autorest.Response
AccessLevel AccessLevel
LeaseStatus LeaseStatus
LeaseState LeaseState
LeaseDuration *LeaseDuration
MetaData map[string]string
HasImmutabilityPolicy bool
HasLegalHold bool
}
type Dataset string
var (
Copy Dataset = "copy"
Deleted Dataset = "deleted"
MetaData Dataset = "metadata"
Snapshots Dataset = "snapshots"
UncommittedBlobs Dataset = "uncommittedblobs"
)
type ErrorResponse struct {
Code *string `xml:"Code"`
Message *string `xml:"Message"`
}
type LeaseDuration string
var (
// If this lease is for a Fixed Duration
Fixed LeaseDuration = "fixed"
// If this lease is for an Indefinite Duration
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
giovanni-0.20.0/storage/2018-11-09/blob/containers/resource_id.go 0000664 0000000 0000000 00000003260 14232154237 0024027 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Container
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, containerName)
}
// GetResourceManagerResourceID returns the Resource Manager specific
// ResourceID for a specific Storage Container
func (client Client) GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, containerName string) string {
fmtStr := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/%s/blobServices/default/containers/%s"
return fmt.Sprintf(fmtStr, subscriptionID, resourceGroup, accountName, containerName)
}
type ResourceID struct {
AccountName string
ContainerName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Container Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
containerName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/resource_id_test.go 0000664 0000000 0000000 00000006654 14232154237 0025100 0 ustar 00root root 0000000 0000000 package containers
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestGetResourceManagerResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.GermanCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.PublicCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceManagerResourceID("11112222-3333-4444-5555-666677778888", "group1", "account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource Manager Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected the container name to be `container1` but got %q", actual.ContainerName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/set_acl.go 0000664 0000000 0000000 00000007651 14232154237 0023146 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetAccessControl sets the Access Control for a Container without a Lease ID
func (client Client) SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error) {
return client.SetAccessControlWithLeaseID(ctx, accountName, containerName, "", level)
}
// SetAccessControlWithLeaseID sets the Access Control for a Container using the specified Lease ID
func (client Client) SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`containerName` cannot be an empty string.")
}
req, err := client.SetAccessControlWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, level)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure responding to request")
return
}
return
}
// SetAccessControlWithLeaseIDPreparer prepares the SetAccessControlWithLeaseID request.
func (client Client) SetAccessControlWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "acl"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, level)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlWithLeaseIDSender sends the SetAccessControlWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlWithLeaseIDResponder handles the response to the SetAccessControlWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/set_metadata.go 0000664 0000000 0000000 00000010137 14232154237 0024160 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the specified MetaData on the Container without a Lease ID
func (client Client) SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error) {
return client.SetMetaDataWithLeaseID(ctx, accountName, containerName, "", metaData)
}
// SetMetaDataWithLeaseID sets the specified MetaData on the Container using the specified Lease ID
func (client Client) SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("containers.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataWithLeaseIDPreparer prepares the SetMetaDataWithLeaseID request.
func (client Client) SetMetaDataWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataWithLeaseIDSender sends the SetMetaDataWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataWithLeaseIDResponder handles the response to the SetMetaDataWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/blob/containers/version.go 0000664 0000000 0000000 00000000470 14232154237 0023211 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/ 0000775 0000000 0000000 00000000000 14232154237 0020734 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/ 0000775 0000000 0000000 00000000000 14232154237 0023303 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/README.md 0000664 0000000 0000000 00000004413 14232154237 0024564 0 ustar 00root root 0000000 0000000 ## Data Lake Storage Gen2 File Systems SDK for API version 2018-11-09
This package allows you to interact with the Data Lake Storage Gen2 File Systems API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
### Example Usage
```go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/go-azure-helpers/authentication"
"github.com/hashicorp/go-azure-helpers/sender"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/datalakestore/filesystems"
)
func Example() error {
accountName := "storageaccount1"
fileSystemName := "filesystem1"
builder := &authentication.Builder{
SubscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"),
ClientID: os.Getenv("ARM_CLIENT_ID"),
ClientSecret: os.Getenv("ARM_CLIENT_SECRET"),
TenantID: os.Getenv("ARM_TENANT_ID"),
Environment: os.Getenv("ARM_ENVIRONMENT"),
// Feature Toggles
SupportsClientSecretAuth: true,
}
c, err := builder.Build()
if err != nil {
return fmt.Errorf("Error building AzureRM Client: %s", err)
}
env, err := authentication.DetermineEnvironment(c.Environment)
if err != nil {
return err
}
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, c.TenantID)
if err != nil {
return err
}
// OAuthConfigForTenant returns a pointer, which can be nil.
if oauthConfig == nil {
return fmt.Errorf("Unable to configure OAuthConfig for tenant %s", c.TenantID)
}
sender := sender.BuildSender("AzureRM")
ctx := context.Background()
storageAuth, err := config.GetAuthorizationToken(sender, oauthConfig, "https://storage.azure.com/")
if err != nil {
return fmt.Errorf("Error retrieving Authorization Token")
}
fileSystemsClient := filesystems.NewWithEnvironment(env)
fileSystemsClient.Client.Authorizer = storageAuth
input := filesystems.CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
return fmt.Errorf("Error creating: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/client.go 0000664 0000000 0000000 00000001216 14232154237 0025110 0 ustar 00root root 0000000 0000000 package filesystems
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Data Lake Storage FileSystem
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Data Lake Storage FileSystem client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Data Lake Storage FileSystem client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/create.go 0000664 0000000 0000000 00000006425 14232154237 0025104 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type CreateInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
}
// Create creates a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Create(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`fileSystemName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure responding to request")
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/create_test.go 0000664 0000000 0000000 00000003202 14232154237 0026131 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCreateHasNoTagsByDefault(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 0 {
t.Fatalf("Expected 0 properties by default but got %d", len(props.Properties))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/delete.go 0000664 0000000 0000000 00000005514 14232154237 0025101 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Delete(ctx context.Context, accountName string, fileSystemName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`fileSystemName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure responding to request")
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/helpers.go 0000664 0000000 0000000 00000002041 14232154237 0025271 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"strings"
)
func buildProperties(input map[string]string) string {
// properties has to be a comma-separated key-value pair
properties := make([]string, 0)
for k, v := range input {
properties = append(properties, fmt.Sprintf("%s=%s", k, v))
}
return strings.Join(properties, ",")
}
func parseProperties(input string) (*map[string]string, error) {
properties := make(map[string]string)
if input == "" {
return &properties, nil
}
// properties is a comma-separated list of key-value pairs
splitProperties := strings.Split(input, ",")
for _, propertyRaw := range splitProperties {
// because these are base64-encoded they're likely to end in at least one =
// as such we can't string split on that -_-
position := strings.Index(propertyRaw, "=")
if position < 0 {
return nil, fmt.Errorf("Expected there to be an equals in the key value pair: %q", propertyRaw)
}
key := propertyRaw[0:position]
value := propertyRaw[position+1:]
properties[key] = value
}
return &properties, nil
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/helpers_test.go 0000664 0000000 0000000 00000002724 14232154237 0026340 0 ustar 00root root 0000000 0000000 package filesystems
import (
"reflect"
"testing"
)
func TestParseProperties(t *testing.T) {
testData := []struct {
name string
input string
expected map[string]string
expectError bool
}{
{
name: "no items",
input: "",
expected: map[string]string{},
expectError: false,
},
{
name: "invalid item",
input: "hello",
expectError: true,
},
{
name: "single item",
input: "hello=world",
expected: map[string]string{
"hello": "world",
},
},
{
name: "single-item-base64",
input: "hello=aGVsbG8=",
expected: map[string]string{
"hello": "aGVsbG8=",
},
expectError: false,
},
{
name: "single-item-base64-multipleequals",
input: "hello=d29uZGVybGFuZA==",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
},
expectError: false,
},
{
name: "multiple-items-base64",
input: "hello=d29uZGVybGFuZA==,private=ZXll",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
expectError: false,
},
}
for _, testCase := range testData {
t.Logf("[DEBUG] Test %q", testCase.name)
actual, err := parseProperties(testCase.input)
if err != nil {
if testCase.expectError {
continue
}
t.Fatalf("[DEBUG] Didn't expect an error but got %s", err)
}
if !reflect.DeepEqual(testCase.expected, *actual) {
t.Fatalf("Expected %+v but got %+v", testCase.expected, *actual)
}
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/lifecycle_test.go 0000664 0000000 0000000 00000005302 14232154237 0026630 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{
"hello": "aGVsbG8=",
},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 1 {
t.Fatalf("Expected 1 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "aGVsbG8=" {
t.Fatalf("Expected `hello` to be `aGVsbG8=` but got %q", props.Properties["hello"])
}
t.Logf("[DEBUG] Updating the properties..")
setInput := SetPropertiesInput{
Properties: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
}
if _, err := fileSystemsClient.SetProperties(ctx, accountName, fileSystemName, setInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Properties..")
props, err = fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 2 {
t.Fatalf("Expected 2 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "d29uZGVybGFuZA==" {
t.Fatalf("Expected `hello` to be `d29uZGVybGFuZA==` but got %q", props.Properties["hello"])
}
if props.Properties["private"] != "ZXll" {
t.Fatalf("Expected `private` to be `ZXll` but got %q", props.Properties["private"])
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/properties_get.go 0000664 0000000 0000000 00000007435 14232154237 0026676 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPropertiesResponse struct {
autorest.Response
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Is Hierarchical Namespace Enabled?
NamespaceEnabled bool
}
// GetProperties gets the properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) GetProperties(ctx context.Context, accountName string, fileSystemName string) (result GetPropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure responding to request")
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResponse, err error) {
if resp != nil && resp.Header != nil {
propertiesRaw := resp.Header.Get("x-ms-properties")
var properties *map[string]string
properties, err = parseProperties(propertiesRaw)
if err != nil {
return
}
result.Properties = *properties
result.NamespaceEnabled = strings.EqualFold(resp.Header.Get("x-ms-namespace-enabled"), "tru")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/properties_set.go 0000664 0000000 0000000 00000007773 14232154237 0026717 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has been modified since the specified date and time.
IfModifiedSince *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has not been modified since the specified date and time.
IfUnmodifiedSince *string
}
// SetProperties sets the Properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) SetProperties(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure responding to request")
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
preparer := autorest.CreatePreparer(
autorest.AsPatch(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/resource_id.go 0000664 0000000 0000000 00000002417 14232154237 0026141 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Data Lake Storage FileSystem
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
type ResourceID struct {
AccountName string
DirectoryName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Data Lake Storage FileSystem API's
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.dfs.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
directoryName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/resource_id_test.go 0000664 0000000 0000000 00000003756 14232154237 0027207 0 ustar 00root root 0000000 0000000 package filesystems
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected the directory name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/filesystems/version.go 0000664 0000000 0000000 00000000471 14232154237 0025321 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/ 0000775 0000000 0000000 00000000000 14232154237 0022053 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/client.go 0000664 0000000 0000000 00000001166 14232154237 0023664 0 ustar 00root root 0000000 0000000 package paths
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Data Lake Storage Path
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Data Lake Storage Path client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Data Lake Storage Path client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/create.go 0000664 0000000 0000000 00000006170 14232154237 0023651 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PathResource string
const PathResourceFile PathResource = "file"
const PathResourceDirectory PathResource = "directory"
type CreateInput struct {
Resource PathResource
}
// Create creates a Data Lake Store Gen2 Path within a Storage Account
func (client Client) Create(ctx context.Context, accountName string, fileSystemName string, path string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`fileSystemName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, fileSystemName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure responding to request")
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, fileSystemName string, path string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", input.Resource),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/create_test.go 0000664 0000000 0000000 00000003512 14232154237 0024705 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/datalakestore/filesystems"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCreateDirectory(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
path := "test"
if _, err = client.BuildTestResourcesWithHns(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := filesystems.NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
fileSystemInput := filesystems.CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, fileSystemInput); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Creating path..")
pathsClient := NewWithEnvironment(client.Environment)
pathsClient.Client = client.PrepareWithStorageResourceManagerAuth(pathsClient.Client)
input := CreateInput{
Resource: PathResourceDirectory,
}
if _, err = pathsClient.Create(ctx, accountName, fileSystemName, path, input); err != nil {
t.Fatal(fmt.Errorf("Error creating path: %s", err))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/delete.go 0000664 0000000 0000000 00000005403 14232154237 0023646 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Delete(ctx context.Context, accountName string, fileSystemName string, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`fileSystemName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, fileSystemName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure responding to request")
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, fileSystemName string, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/helpers.go 0000664 0000000 0000000 00000000431 14232154237 0024042 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
)
func parsePathResource(input string) (PathResource, error) {
switch input {
case "file":
return PathResourceFile, nil
case "directory":
return PathResourceDirectory, nil
}
return "", fmt.Errorf("Unhandled path resource type %q", input)
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/lifecycle_test.go 0000664 0000000 0000000 00000007307 14232154237 0025407 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/datalakestore/filesystems"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
const defaultACLString = "user::rwx,group::r-x,other::---"
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
path := "test"
if _, err = client.BuildTestResourcesWithHns(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := filesystems.NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
pathsClient := NewWithEnvironment(client.Environment)
pathsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
fileSystemInput := filesystems.CreateInput{}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, fileSystemInput); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Creating folder 'test' ..")
input := CreateInput{
Resource: PathResourceDirectory,
}
if _, err = pathsClient.Create(ctx, accountName, fileSystemName, path, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' ..")
props, err := pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
t.Logf("[DEBUG] Props.Owner: %q", props.Owner)
t.Logf("[DEBUG] Props.Group: %q", props.Group)
t.Logf("[DEBUG] Props.ACL: %q", props.ACL)
t.Logf("[DEBUG] Props.ETag: %q", props.ETag)
t.Logf("[DEBUG] Props.LastModified: %q", props.LastModified)
if props.ACL != defaultACLString {
t.Fatal(fmt.Errorf("Expected Default ACL %q, got %q", defaultACLString, props.ACL))
}
newACL := "user::rwx,group::r-x,other::r-x,default:user::rwx,default:group::r-x,default:other::---"
accessControlInput := SetAccessControlInput{
ACL: &newACL,
}
t.Logf("[DEBUG] Setting Access Control for folder 'test' ..")
if _, err = pathsClient.SetAccessControl(ctx, accountName, fileSystemName, path, accessControlInput); err != nil {
t.Fatal(fmt.Errorf("Error setting Access Control %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' (2) ..")
props, err = pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties (2): %s", err))
}
if props.ACL != newACL {
t.Fatal(fmt.Errorf("Expected new ACL %q, got %q", newACL, props.ACL))
}
t.Logf("[DEBUG] Deleting path 'test' ..")
if _, err = pathsClient.Delete(ctx, accountName, fileSystemName, path); err != nil {
t.Fatal(fmt.Errorf("Error deleting path: %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' (3) ..")
props, err = pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err == nil {
t.Fatal(fmt.Errorf("Didn't get error getting properties after deleting path (3)"))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting filesystem: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/properties_get.go 0000664 0000000 0000000 00000010721 14232154237 0025436 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPropertiesResponse struct {
autorest.Response
ETag string
LastModified time.Time
// ResourceType is only returned for GetPropertiesActionGetStatus requests
ResourceType PathResource
Owner string
Group string
// ACL is only returned for GetPropertiesActionGetAccessControl requests
ACL string
}
type GetPropertiesAction string
const (
GetPropertiesActionGetStatus GetPropertiesAction = "getStatus"
GetPropertiesActionGetAccessControl GetPropertiesAction = "getAccessControl"
)
// GetProperties gets the properties for a Data Lake Store Gen2 Path in a FileSystem within a Storage Account
func (client Client) GetProperties(ctx context.Context, accountName string, fileSystemName string, path string, action GetPropertiesAction) (result GetPropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, fileSystemName, path, action)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure responding to request")
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string, path string, action GetPropertiesAction) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"action": autorest.Encode("query", string(action)),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResponse, err error) {
result = GetPropertiesResponse{}
if resp != nil && resp.Header != nil {
resourceTypeRaw := resp.Header.Get("x-ms-resource-type")
var resourceType PathResource
if resourceTypeRaw != "" {
resourceType, err = parsePathResource(resourceTypeRaw)
if err != nil {
return GetPropertiesResponse{}, err
}
result.ResourceType = resourceType
}
result.ETag = resp.Header.Get("ETag")
if lastModifiedRaw := resp.Header.Get("Last-Modified"); lastModifiedRaw != "" {
lastModified, err := time.Parse(time.RFC1123, lastModifiedRaw)
if err != nil {
return GetPropertiesResponse{}, err
}
result.LastModified = lastModified
}
result.Owner = resp.Header.Get("x-ms-owner")
result.Group = resp.Header.Get("x-ms-group")
result.ACL = resp.Header.Get("x-ms-acl")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return result, err
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/properties_set.go 0000664 0000000 0000000 00000010024 14232154237 0025446 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetAccessControlInput struct {
Owner *string
Group *string
ACL *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has been modified since the specified date and time.
IfModifiedSince *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has not been modified since the specified date and time.
IfUnmodifiedSince *string
}
// SetProperties sets the access control properties for a Data Lake Store Gen2 Path within a Storage Account File System
func (client Client) SetAccessControl(ctx context.Context, accountName string, fileSystemName string, path string, input SetAccessControlInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "SetAccessControl", "`fileSystemName` cannot be an empty string.")
}
req, err := client.SetAccessControlPreparer(ctx, accountName, fileSystemName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", resp, "Failure responding to request")
}
return
}
// SetAccessControlPreparer prepares the SetAccessControl request.
func (client Client) SetAccessControlPreparer(ctx context.Context, accountName string, fileSystemName string, path string, input SetAccessControlInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"action": autorest.Encode("query", "setAccessControl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.Owner != nil {
headers["x-ms-owner"] = *input.Owner
}
if input.Group != nil {
headers["x-ms-group"] = *input.Group
}
if input.ACL != nil {
headers["x-ms-acl"] = *input.ACL
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
preparer := autorest.CreatePreparer(
autorest.AsPatch(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlSender sends the SetAccessControl request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlResponder handles the response to the SetAccessControl request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/resource_id.go 0000664 0000000 0000000 00000003140 14232154237 0024703 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Data Lake Storage FileSystem
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, fileSystemName, path string) string {
domain := endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, fileSystemName, path)
}
type ResourceID struct {
AccountName string
FileSystemName string
Path string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Data Lake Storage FileSystem API's
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.dfs.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
fileSystemAndPath := strings.TrimPrefix(uri.Path, "/")
separatorIndex := strings.Index(fileSystemAndPath, "/")
var fileSystem, path string
if separatorIndex < 0 {
fileSystem = fileSystemAndPath
path = ""
} else {
fileSystem = fileSystemAndPath[0:separatorIndex]
path = fileSystemAndPath[separatorIndex+1:]
}
return &ResourceID{
AccountName: *accountName,
FileSystemName: fileSystem,
Path: path,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/resource_id_test.go 0000664 0000000 0000000 00000004353 14232154237 0025751 0 ustar 00root root 0000000 0000000 package paths
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
AccountName string
FileSystemName string
Path string
Expected string
}{
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "test",
Expected: "https://account1.dfs.core.windows.net/fs1/test",
},
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "test/test2",
Expected: "https://account1.dfs.core.windows.net/fs1/test/test2",
},
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "",
Expected: "https://account1.dfs.core.windows.net/fs1/",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Path %q", v.Path)
c := NewWithEnvironment(azure.PublicCloud)
actual := c.GetResourceID(v.AccountName, v.FileSystemName, v.Path)
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Input string
AccountName string
FileSystemName string
Path string
}{
{
Input: "https://account1.dfs.core.windows.net/fs1/test",
AccountName: "account1",
FileSystemName: "fs1",
Path: "test",
},
{
Input: "https://account1.dfs.core.windows.net/fs1/test/test2",
AccountName: "account1",
FileSystemName: "fs1",
Path: "test/test2",
},
{
Input: "https://account1.dfs.core.windows.net/fs1/",
AccountName: "account1",
FileSystemName: "fs1",
Path: "",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Path %q", v.Path)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != v.AccountName {
t.Fatalf("Expected the account name to be `%q` but got %q", v.AccountName, actual.AccountName)
}
if actual.FileSystemName != v.FileSystemName {
t.Fatalf("Expected the file system name to be `%q` but got %q", v.FileSystemName, actual.FileSystemName)
}
if actual.Path != v.Path {
t.Fatalf("Expected the path to be `%q` but got %q", v.Path, actual.Path)
}
}
}
giovanni-0.20.0/storage/2018-11-09/datalakestore/paths/version.go 0000664 0000000 0000000 00000000463 14232154237 0024072 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/file/ 0000775 0000000 0000000 00000000000 14232154237 0017030 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/file/directories/ 0000775 0000000 0000000 00000000000 14232154237 0021344 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/file/directories/README.md 0000664 0000000 0000000 00000002135 14232154237 0022624 0 ustar 00root root 0000000 0000000 ## File Storage Directories SDK for API version 2018-11-09
This package allows you to interact with the Directories File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/directories"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
directoriesClient := directories.New()
directoriesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := directoriesClient.Create(ctx, accountName, shareName, directoryName, metadata); err != nil {
return fmt.Errorf("Error creating Directory: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/file/directories/api.go 0000664 0000000 0000000 00000001375 14232154237 0022452 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageDirectory interface {
Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error)
SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error)
GetResourceID(accountName, shareName, directoryName string) string
Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error)
}
giovanni-0.20.0/storage/2018-11-09/file/directories/client.go 0000664 0000000 0000000 00000001132 14232154237 0023146 0 ustar 00root root 0000000 0000000 package directories
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/file/directories/create.go 0000664 0000000 0000000 00000007054 14232154237 0023144 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates a new directory under the specified share or parent directory.
func (client Client) Create(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Create", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Create", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/directories/delete.go 0000664 0000000 0000000 00000006343 14232154237 0023143 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete removes the specified empty directory
// Note that the directory must be empty before it can be deleted.
func (client Client) Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Delete", "`path` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/directories/get.go 0000664 0000000 0000000 00000007432 14232154237 0022460 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
// A set of name-value pairs that contain metadata for the directory.
MetaData map[string]string
// The value of this header is set to true if the directory metadata is completely
// encrypted using the specified algorithm. Otherwise, the value is set to false.
DirectoryMetaDataEncrypted bool
}
// Get returns all system properties for the specified directory,
// and can also be used to check the existence of a directory.
func (client Client) Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Get", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Get", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Get", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Get", "`path` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
result.DirectoryMetaDataEncrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/directories/lifecycle_test.go 0000664 0000000 0000000 00000007342 14232154237 0024677 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var StorageFile = Client{}
func TestDirectoriesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
directoriesClient := NewWithEnvironment(client.Environment)
directoriesClient.Client = client.PrepareWithAuthorizer(directoriesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, true)
metaData := map[string]string{
"hello": "world",
}
log.Printf("[DEBUG] Creating Top Level..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello", metaData); err != nil {
t.Fatalf("Error creating Top Level Directory: %s", err)
}
log.Printf("[DEBUG] Creating Inner..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello/there", metaData); err != nil {
t.Fatalf("Error creating Inner Directory: %s", err)
}
log.Printf("[DEBUG] Retrieving share")
innerDir, err := directoriesClient.Get(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving Inner Directory: %s", err)
}
if innerDir.DirectoryMetaDataEncrypted != true {
t.Fatalf("Expected MetaData to be encrypted but got: %t", innerDir.DirectoryMetaDataEncrypted)
}
if len(innerDir.MetaData) != 1 {
t.Fatalf("Expected MetaData to contain 1 item but got %d", len(innerDir.MetaData))
}
if innerDir.MetaData["hello"] != "world" {
t.Fatalf("Expected MetaData `hello` to be `world`: %s", innerDir.MetaData["hello"])
}
log.Printf("[DEBUG] Setting MetaData")
updatedMetaData := map[string]string{
"panda": "pops",
}
if _, err := directoriesClient.SetMetaData(ctx, accountName, shareName, "hello/there", updatedMetaData); err != nil {
t.Fatalf("Error updating MetaData: %s", err)
}
log.Printf("[DEBUG] Retrieving MetaData")
retrievedMetaData, err := directoriesClient.GetMetaData(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving the updated metadata: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected the updated metadata to have 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["panda"] != "pops" {
t.Fatalf("Expected the metadata `panda` to be `pops` but got %q", retrievedMetaData.MetaData["panda"])
}
t.Logf("[DEBUG] Deleting Inner..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello/there"); err != nil {
t.Fatalf("Error deleting Inner Directory: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello"); err != nil {
t.Fatalf("Error deleting Top Level Directory: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/file/directories/metadata_get.go 0000664 0000000 0000000 00000007127 14232154237 0024321 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns all user-defined metadata for the specified directory
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`path` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/directories/metadata_set.go 0000664 0000000 0000000 00000007273 14232154237 0024337 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates user defined metadata for the specified directory
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/directories/resource_id.go 0000664 0000000 0000000 00000003113 14232154237 0024174 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Directory
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, shareName, directoryName)
}
type ResourceID struct {
AccountName string
DirectoryName string
ShareName string
}
// ParseResourceID parses the Resource ID into an Object
// which can be used to interact with the Directory within the File Share
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar/Folder
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/file/directories/resource_id_test.go 0000664 0000000 0000000 00000004246 14232154237 0025243 0 ustar 00root root 0000000 0000000 package directories
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/file/directories/version.go 0000664 0000000 0000000 00000000471 14232154237 0023362 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/file/files/ 0000775 0000000 0000000 00000000000 14232154237 0020132 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/file/files/README.md 0000664 0000000 0000000 00000002064 14232154237 0021413 0 ustar 00root root 0000000 0000000 ## File Storage Files SDK for API version 2018-11-09
This package allows you to interact with the Files File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/files"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
fileName := "example.txt"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
filesClient := files.New()
filesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := files.CreateInput{}
if _, err := filesClient.Create(ctx, accountName, shareName, directoryName, fileName, input); err != nil {
return fmt.Errorf("Error creating File: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/file/files/api.go 0000664 0000000 0000000 00000004234 14232154237 0021235 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
)
type StorageFile interface {
PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error)
GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error)
ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error)
SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error)
PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error
Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error)
SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error)
AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error)
GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error)
GetResourceID(accountName, shareName, directoryName, filePath string) string
ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error)
GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error)
Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error)
CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error)
}
giovanni-0.20.0/storage/2018-11-09/file/files/client.go 0000664 0000000 0000000 00000001124 14232154237 0021735 0 ustar 00root root 0000000 0000000 package files
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/file/files/copy.go 0000664 0000000 0000000 00000011216 14232154237 0021434 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the URL of the source file or blob, up to 2 KB in length.
//
// To copy a file to another file within the same storage account, you may use Shared Key to authenticate
// the source file. If you are copying a file from another storage account, or if you are copying a blob from
// the same storage account or another storage account, then you must authenticate the source file or blob using a
// shared access signature. If the source is a public blob, no authentication is required to perform the copy
// operation. A file in a share snapshot can also be specified as a copy source.
CopySource string
MetaData map[string]string
}
type CopyResult struct {
autorest.Response
// The CopyID, which can be passed to AbortCopy to abort the copy.
CopyID string
// Either `success` or `pending`
CopySuccess string
}
// Copy copies a blob or file to a destination file within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Copy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Copy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Copy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Copy", "`fileName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("files.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Copy", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CopyPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopySuccess = resp.Header.Get("x-ms-copy-status")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/copy_abort.go 0000664 0000000 0000000 00000007157 14232154237 0022634 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// AbortCopy aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata
func (client Client) AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`fileName` cannot be an empty string.")
}
if copyID == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`copyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, shareName, path, fileName, copyID)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, shareName, path, fileName, copyID string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", copyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/copy_wait.go 0000664 0000000 0000000 00000002414 14232154237 0022460 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
)
type CopyAndWaitResult struct {
autorest.Response
CopyID string
}
const DefaultCopyPollDuration = 15 * time.Second
// CopyAndWait is a convenience method which doesn't exist in the API, which copies the file and then waits for the copy to complete
func (client Client) CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error) {
copy, e := client.Copy(ctx, accountName, shareName, path, fileName, input)
if err != nil {
result.Response = copy.Response
err = fmt.Errorf("Error copying: %s", e)
return
}
result.CopyID = copy.CopyID
// since the API doesn't return a LRO, this is a hack which also polls every 10s, but should be sufficient
for true {
props, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if e != nil {
result.Response = copy.Response
err = fmt.Errorf("Error waiting for copy: %s", e)
return
}
switch strings.ToLower(props.CopyStatus) {
case "pending":
time.Sleep(pollDuration)
continue
case "success":
return
default:
err = fmt.Errorf("Unexpected CopyState %q", e)
return
}
}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/copy_wait_test.go 0000664 0000000 0000000 00000011043 14232154237 0023515 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestFilesCopyAndWaitFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
copiedFileName := "ubuntu.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
func TestFilesCopyAndWaitFromBlob(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
originalFileName := "ubuntu.iso"
copiedFileName := "ubuntu-copied.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting the original file..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", originalFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Now copying that blob..")
duplicateInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetFileEndpoint(filesClient.BaseURI, accountName), shareName, originalFileName),
}
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, duplicateInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copying duplicate: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
giovanni-0.20.0/storage/2018-11-09/file/files/create.go 0000664 0000000 0000000 00000011330 14232154237 0021722 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// This header specifies the maximum size for the file, up to 1 TiB.
ContentLength int64
// The MIME content type of the file
// If not specified, the default type is application/octet-stream.
ContentType *string
// Specifies which content encodings have been applied to the file.
// This value is returned to the client when the Get File operation is performed
// on the file resource and can be used to decode file content.
ContentEncoding *string
// Specifies the natural languages used by this resource.
ContentLanguage *string
// The File service stores this value but does not use or modify it.
CacheControl *string
// Sets the file's MD5 hash.
ContentMD5 *string
// Sets the file’s Content-Disposition header.
ContentDisposition *string
MetaData map[string]string
}
// Create creates a new file or replaces a file.
func (client Client) Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Create", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Create", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Create", "`input.MetaData` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-content-length": input.ContentLength,
"x-ms-type": "file",
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/delete.go 0000664 0000000 0000000 00000006206 14232154237 0021727 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete immediately deletes the file from the File Share.
func (client Client) Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Delete", "`fileName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/lifecycle_test.go 0000664 0000000 0000000 00000011764 14232154237 0023470 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageFile = Client{}
func TestFilesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
fileName := "bled5.png"
contentEncoding := "application/vnd+panda"
t.Logf("[DEBUG] Creating Top Level File..")
createInput := CreateInput{
ContentLength: 1024,
ContentEncoding: &contentEncoding,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Top-Level File..")
file, err := filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 1024 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != contentEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", contentEncoding, file.ContentEncoding)
}
updatedSize := int64(2048)
updatedEncoding := "application/vnd+pandas2"
updatedInput := SetPropertiesInput{
ContentEncoding: &updatedEncoding,
ContentLength: &updatedSize,
}
t.Logf("[DEBUG] Setting Properties for the Top-Level File..")
if _, err := filesClient.SetProperties(ctx, accountName, shareName, "", fileName, updatedInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Properties for the Top-Level File..")
file, err = filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 2048 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != updatedEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", updatedEncoding, file.ContentEncoding)
}
t.Logf("[DEBUG] Setting MetaData..")
metaData := map[string]string{
"hello": "there",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Retrieving MetaData..")
retrievedMetaData, err := filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
t.Logf("[DEBUG] Re-Setting MetaData..")
metaData = map[string]string{
"hello": "there",
"second": "thing",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving MetaData..")
retrievedMetaData, err = filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 2 {
t.Fatalf("Expected 2 items but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
if retrievedMetaData.MetaData["second"] != "thing" {
t.Fatalf("Expected `second` to be `thing` but got %q", retrievedMetaData.MetaData["second"])
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/file/files/metadata_get.go 0000664 0000000 0000000 00000007263 14232154237 0023110 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData for the specified File.
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`fileName` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
//metadata.ByParsingFromHeaders(&result.MetaData),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/metadata_set.go 0000664 0000000 0000000 00000007347 14232154237 0023127 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates the specified File to have the specified MetaData.
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("files.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, fileName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/properties_get.go 0000664 0000000 0000000 00000012146 14232154237 0023520 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
CacheControl string
ContentDisposition string
ContentEncoding string
ContentLanguage string
ContentLength *int64
ContentMD5 string
ContentType string
CopyID string
CopyStatus string
CopySource string
CopyProgress string
CopyStatusDescription string
CopyCompletionTime string
Encrypted bool
MetaData map[string]string
}
// GetProperties returns the Properties for the specified file
func (client Client) GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("x-ms-content-md5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = resp.Header.Get("x-ms-copy-status")
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.Encrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
contentLengthRaw := resp.Header.Get("Content-Length")
if contentLengthRaw != "" {
contentLength, err := strconv.Atoi(contentLengthRaw)
if err != nil {
return result, fmt.Errorf("Error parsing %q for Content-Length as an integer: %s", contentLengthRaw, err)
}
contentLengthI64 := int64(contentLength)
result.ContentLength = &contentLengthI64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/properties_set.go 0000664 0000000 0000000 00000013714 14232154237 0023536 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
// Resizes a file to the specified size.
// If the specified byte value is less than the current size of the file,
// then all ranges above the specified byte value are cleared.
ContentLength *int64
// Modifies the cache control string for the file.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentControl *string
// Sets the file’s Content-Disposition header.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentDisposition *string
// Sets the file's content encoding.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentEncoding *string
// Sets the file's content language.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentLanguage *string
// Sets the file's MD5 hash.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentMD5 *string
// Sets the file's content type.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentType *string
}
// SetProperties sets the specified properties on the specified File
func (client Client) SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-type": "file",
}
if input.ContentControl != nil {
headers["x-ms-cache-control"] = *input.ContentControl
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-content-language"] = *input.ContentLanguage
}
if input.ContentLength != nil {
headers["x-ms-content-length"] = *input.ContentLength
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/range_clear.go 0000664 0000000 0000000 00000007740 14232154237 0022733 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ClearByteRangeInput struct {
StartBytes int64
EndBytes int64
}
// ClearByteRange clears the specified Byte Range from within the specified File
func (client Client) ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.EndBytes` must be greater than 0.")
}
req, err := client.ClearByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", nil, "Failure preparing request")
return
}
resp, err := client.ClearByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure sending request")
return
}
result, err = client.ClearByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure responding to request")
return
}
return
}
// ClearByteRangePreparer prepares the ClearByteRange request.
func (client Client) ClearByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes),
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ClearByteRangeSender sends the ClearByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ClearByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ClearByteRangeResponder handles the response to the ClearByteRange request. The method always
// closes the http.Response Body.
func (client Client) ClearByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/range_get.go 0000664 0000000 0000000 00000010430 14232154237 0022412 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetByteRangeInput struct {
StartBytes int64
EndBytes int64
}
type GetByteRangeResult struct {
autorest.Response
Contents []byte
}
// GetByteRange returns the specified Byte Range from the specified File.
func (client Client) GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at most 4MB.")
}
req, err := client.GetByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", nil, "Failure preparing request")
return
}
resp, err := client.GetByteRangeSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure sending request")
return
}
result, err = client.GetByteRangeResponder(resp, expectedBytes)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure responding to request")
return
}
return
}
// GetByteRangePreparer prepares the GetByteRange request.
func (client Client) GetByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetByteRangeSender sends the GetByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetByteRangeResponder handles the response to the GetByteRange request. The method always
// closes the http.Response Body.
func (client Client) GetByteRangeResponder(resp *http.Response, length int64) (result GetByteRangeResult, err error) {
result.Contents = make([]byte, length)
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/range_get_file.go 0000664 0000000 0000000 00000006055 14232154237 0023421 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"log"
"math"
"runtime"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// GetFile is a helper method to download a file by chunking it automatically
func (client Client) GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error) {
// first look up the file and check out how many bytes it is
file, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if err != nil {
result = file.Response
err = e
return
}
if file.ContentLength == nil {
err = fmt.Errorf("Content-Length was nil!")
return
}
length := int64(*file.ContentLength)
chunkSize := int64(4 * 1024 * 1024) // 4MB
if chunkSize > length {
chunkSize = length
}
// then split that up into chunks and retrieve it retrieve it into the 'results' set
chunks := int(math.Ceil(float64(length) / float64(chunkSize)))
workerCount := parallelism * runtime.NumCPU()
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
results := make([]*downloadFileChunkResult, chunks)
errors := make(chan error, chunkSize)
for i := 0; i < chunks; i++ {
go func(i int) {
log.Printf("[DEBUG] Downloading Chunk %d of %d", i+1, chunks)
dfci := downloadFileChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: length,
}
result, err := client.downloadFileChunk(ctx, accountName, shareName, path, fileName, dfci)
if err != nil {
errors <- err
waitGroup.Done()
return
}
// if there's no error, we should have bytes, so this is safe
results[i] = result
waitGroup.Done()
}(i)
}
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
err = fmt.Errorf("Error downloading file: %s", <-errors)
return
}
// then finally put it all together, in order and return it
output := make([]byte, length)
for _, v := range results {
copy(output[v.startBytes:v.endBytes], v.bytes)
}
outputBytes = output
return
}
type downloadFileChunkInput struct {
thisChunk int
chunkSize int64
fileSize int64
}
type downloadFileChunkResult struct {
startBytes int64
endBytes int64
bytes []byte
}
func (client Client) downloadFileChunk(ctx context.Context, accountName, shareName, path, fileName string, input downloadFileChunkInput) (*downloadFileChunkResult, error) {
startBytes := input.chunkSize * int64(input.thisChunk)
endBytes := startBytes + input.chunkSize
// the last chunk may exceed the size of the file
remaining := input.fileSize - startBytes
if input.chunkSize > remaining {
endBytes = startBytes + remaining
}
getInput := GetByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
}
result, err := client.GetByteRange(ctx, accountName, shareName, path, fileName, getInput)
if err != nil {
return nil, fmt.Errorf("Error putting bytes: %s", err)
}
output := downloadFileChunkResult{
startBytes: startBytes,
endBytes: endBytes,
bytes: result.Contents,
}
return &output, nil
}
giovanni-0.20.0/storage/2018-11-09/file/files/range_get_file_test.go 0000664 0000000 0000000 00000007063 14232154237 0024460 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestGetSmallFile(t *testing.T) {
// the purpose of this test is to verify that the small, single-chunked file gets downloaded correctly
testGetFile(t, "small-file.png", "image/png")
}
func TestGetLargeFile(t *testing.T) {
// the purpose of this test is to verify that the large, multi-chunked file gets downloaded correctly
testGetFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testGetFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Downloading file..")
_, downloadedBytes, err := filesClient.GetFile(ctx, accountName, shareName, "", fileName, 4)
if err != nil {
t.Fatalf("Error downloading file: %s", err)
}
t.Logf("[DEBUG] Asserting the files are the same size..")
expectedBytes := make([]byte, info.Size())
file.Read(expectedBytes)
if len(expectedBytes) != len(downloadedBytes) {
t.Fatalf("Expected %d bytes but got %d", len(expectedBytes), len(downloadedBytes))
}
t.Logf("[DEBUG] Asserting the files are the same content-wise..")
// overkill, but it's this or shasum-ing
for i := int64(0); i < info.Size(); i++ {
if expectedBytes[i] != downloadedBytes[i] {
t.Fatalf("Expected byte %d to be %q but got %q", i, expectedBytes[i], downloadedBytes[i])
}
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/file/files/range_put.go 0000664 0000000 0000000 00000011226 14232154237 0022447 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutByteRangeInput struct {
StartBytes int64
EndBytes int64
// Content is the File Contents for the specified range
// which can be at most 4MB
Content []byte
}
// PutByteRange puts the specified Byte Range in the specified File.
func (client Client) PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
actualBytes := len(input.Content)
if expectedBytes != int64(actualBytes) {
return result, validation.NewError("files.Client", "PutByteRange", fmt.Sprintf("The specified byte-range (%d) didn't match the content size (%d).", expectedBytes, actualBytes))
}
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at most 4MB.")
}
req, err := client.PutByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", nil, "Failure preparing request")
return
}
resp, err := client.PutByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure sending request")
return
}
result, err = client.PutByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure responding to request")
return
}
return
}
// PutByteRangePreparer prepares the PutByteRange request.
func (client Client) PutByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
"Content-Length": int(len(input.Content)),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutByteRangeSender sends the PutByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutByteRangeResponder handles the response to the PutByteRange request. The method always
// closes the http.Response Body.
func (client Client) PutByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/range_put_file.go 0000664 0000000 0000000 00000005070 14232154237 0023446 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"io"
"log"
"math"
"os"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// PutFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
chunkSize := 4 * 1024 * 1024 // 4MB
if chunkSize > int(fileSize) {
chunkSize = int(fileSize)
}
chunks := int(math.Ceil(float64(fileSize) / float64(chunkSize*1.0)))
workerCount := parallelism
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
jobs := make(chan int, workerCount)
errors := make(chan error, chunkSize)
for i := 0; i < workerCount; i++ {
go func() {
for i := range jobs {
log.Printf("[DEBUG] Chunk %d of %d", i+1, chunks)
uci := uploadChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: fileSize,
}
_, err := client.uploadChunk(ctx, accountName, shareName, path, fileName, uci, file)
if err != nil {
errors <- err
}
}
waitGroup.Done()
}()
}
for i := 0; i < chunks; i++ {
jobs <- i
}
close(jobs)
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
return fmt.Errorf("Error uploading file: %s", <-errors)
}
return nil
}
type uploadChunkInput struct {
thisChunk int
chunkSize int
fileSize int64
}
func (client Client) uploadChunk(ctx context.Context, accountName, shareName, path, fileName string, input uploadChunkInput, file *os.File) (result autorest.Response, err error) {
startBytes := int64(input.chunkSize * input.thisChunk)
endBytes := startBytes + int64(input.chunkSize)
// the last size may exceed the size of the file
remaining := input.fileSize - startBytes
if int64(input.chunkSize) > remaining {
endBytes = startBytes + remaining
}
bytesToRead := int(endBytes) - int(startBytes)
bytes := make([]byte, bytesToRead)
_, err = file.ReadAt(bytes, startBytes)
if err != nil {
if err != io.EOF {
return result, fmt.Errorf("Error reading bytes: %s", err)
}
}
putBytesInput := PutByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
Content: bytes,
}
result, err = client.PutByteRange(ctx, accountName, shareName, path, fileName, putBytesInput)
if err != nil {
return result, fmt.Errorf("Error putting bytes: %s", err)
}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/range_put_file_test.go 0000664 0000000 0000000 00000005413 14232154237 0024506 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPutSmallFile(t *testing.T) {
// the purpose of this test is to ensure that a small file (< 4MB) is a single chunk
testPutFile(t, "small-file.png", "image/png")
}
func TestPutLargeFile(t *testing.T) {
// the purpose of this test is to ensure that large files (> 4MB) are chunked
testPutFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testPutFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/file/files/ranges_list.go 0000664 0000000 0000000 00000007277 14232154237 0023010 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListRangesResult struct {
autorest.Response
Ranges []Range `xml:"Range"`
}
type Range struct {
Start string `xml:"Start"`
End string `xml:"End"`
}
// ListRanges returns the list of valid ranges for the specified File.
func (client Client) ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("files.Client", "ListRanges", "`path` cannot be an empty string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`fileName` cannot be an empty string.")
}
req, err := client.ListRangesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", nil, "Failure preparing request")
return
}
resp, err := client.ListRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure sending request")
return
}
result, err = client.ListRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure responding to request")
return
}
return
}
// ListRangesPreparer prepares the ListRanges request.
func (client Client) ListRangesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "rangelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListRangesSender sends the ListRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListRangesResponder handles the response to the ListRanges request. The method always
// closes the http.Response Body.
func (client Client) ListRangesResponder(resp *http.Response) (result ListRangesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/files/resource_id.go 0000664 0000000 0000000 00000003654 14232154237 0022774 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName, filePath string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s/%s", domain, shareName, directoryName, filePath)
}
type ResourceID struct {
AccountName string
DirectoryName string
FileName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with Files within a Storage Share.
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
fileName := segments[len(segments)-1]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
directoryName = strings.TrimSuffix(directoryName, fileName)
directoryName = strings.TrimSuffix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
FileName: fileName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/file/files/resource_id_test.go 0000664 0000000 0000000 00000007430 14232154237 0024027 0 ustar 00root root 0000000 0000000 package files
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1", "file1.txt")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/directory2/file1.txt",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1/directory2" {
t.Fatalf("Expected Directory Name to be `directory1/directory2` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/file/files/version.go 0000664 0000000 0000000 00000000463 14232154237 0022151 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/file/shares/ 0000775 0000000 0000000 00000000000 14232154237 0020315 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/file/shares/README.md 0000664 0000000 0000000 00000001777 14232154237 0021610 0 ustar 00root root 0000000 0000000 ## File Storage Shares SDK for API version 2018-11-09
This package allows you to interact with the Shares File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
sharesClient := shares.New()
sharesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := shares.CreateInput{
QuotaInGB: 2,
}
if _, err := sharesClient.Create(ctx, accountName, shareName, input); err != nil {
return fmt.Errorf("Error creating Share: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/file/shares/acl_get.go 0000664 0000000 0000000 00000006213 14232154237 0022244 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL get the Access Control List for the specified Storage Share
func (client Client) GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.GetACLPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/acl_set.go 0000664 0000000 0000000 00000006415 14232154237 0022264 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"encoding/xml"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List on the specified Storage Share
func (client Client) SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.SetACLPreparer(ctx, accountName, shareName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/api.go 0000664 0000000 0000000 00000003205 14232154237 0021415 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageShare interface {
SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error)
GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error)
GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error)
GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error)
SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error)
SetProperties(ctx context.Context, accountName, shareName string, newQuotaGB int) (result autorest.Response, err error)
DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error)
CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error)
GetResourceID(accountName, shareName string) string
GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, shareName string) string
GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error)
Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2018-11-09/file/shares/client.go 0000664 0000000 0000000 00000001125 14232154237 0022121 0 ustar 00root root 0000000 0000000 package shares
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/file/shares/create.go 0000664 0000000 0000000 00000007365 14232154237 0022122 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies the maximum size of the share, in gigabytes.
// Must be greater than 0, and less than or equal to 5TB (5120).
QuotaInGB int
MetaData map[string]string
}
// Create creates the specified Storage Share within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Create", "`shareName` must be a lower-cased string.")
}
if input.QuotaInGB <= 0 || input.QuotaInGB > 102400 {
return result, validation.NewError("shares.Client", "Create", "`input.QuotaInGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": input.QuotaInGB,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/delete.go 0000664 0000000 0000000 00000006120 14232154237 0022105 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Storage Share from within a Storage Account
func (client Client) Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Delete", "`shareName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, deleteSnapshots)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if deleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/lifecycle_test.go 0000664 0000000 0000000 00000021030 14232154237 0023636 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageShare = Client{}
func TestSharesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 5)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 5 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
func TestSharesLifecycleLargeQuota(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResourcesWithSku(ctx, resourceGroup, accountName, storage.KindFileStorage, storage.SkuNamePremiumLRS)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1001,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1001 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 6000)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 6000 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/file/shares/metadata_get.go 0000664 0000000 0000000 00000006525 14232154237 0023273 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData associated with the specified Storage Share
func (client Client) GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/metadata_set.go 0000664 0000000 0000000 00000006703 14232154237 0023305 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the MetaData on the specified Storage Share
func (client Client) SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("shares.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/models.go 0000664 0000000 0000000 00000000416 14232154237 0022130 0 ustar 00root root 0000000 0000000 package shares
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2018-11-09/file/shares/properties_get.go 0000664 0000000 0000000 00000007150 14232154237 0023702 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesResult struct {
autorest.Response
MetaData map[string]string
ShareQuota int
}
// GetProperties returns the properties about the specified Storage Share
func (client Client) GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
quotaRaw := resp.Header.Get("x-ms-share-quota")
if quotaRaw != "" {
quota, e := strconv.Atoi(quotaRaw)
if e != nil {
return result, fmt.Errorf("Error converting %q to an integer: %s", quotaRaw, err)
}
result.ShareQuota = quota
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/properties_set.go 0000664 0000000 0000000 00000006617 14232154237 0023725 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetProperties lets you update the Quota for the specified Storage Share
func (client Client) SetProperties(ctx context.Context, accountName, shareName string, newQuotaGB int) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if newQuotaGB <= 0 || newQuotaGB > 102400 {
return result, validation.NewError("shares.Client", "SetProperties", "`newQuotaGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, newQuotaGB)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName string, quotaGB int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": quotaGB,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/resource_id.go 0000664 0000000 0000000 00000003217 14232154237 0023152 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File Share
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
// GetResourceManagerResourceID returns the Resource Manager specific
// ResourceID for a specific Storage Share
func (client Client) GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, shareName string) string {
fmtStr := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/%s/fileServices/default/shares/%s"
return fmt.Sprintf(fmtStr, subscriptionID, resourceGroup, accountName, shareName)
}
type ResourceID struct {
AccountName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Storage Shares SDK
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
shareName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/file/shares/resource_id_test.go 0000664 0000000 0000000 00000006514 14232154237 0024214 0 ustar 00root root 0000000 0000000 package shares
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestGetResourceManagerResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.GermanCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.PublicCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceManagerResourceID("11112222-3333-4444-5555-666677778888", "group1", "account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource Manager Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected the share name to be `share1` but got %q", actual.ShareName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/file/shares/snapshot_create.go 0000664 0000000 0000000 00000010266 14232154237 0024033 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateSnapshotInput struct {
MetaData map[string]string
}
type CreateSnapshotResult struct {
autorest.Response
// This header is a DateTime value that uniquely identifies the share snapshot.
// The value of this header may be used in subsequent requests to access the share snapshot.
// This value is opaque.
SnapshotDateTime string
}
// CreateSnapshot creates a read-only snapshot of the share
// A share can support creation of 200 share snapshots. Attempting to create more than 200 share snapshots fails with 409 (Conflict).
// Attempting to create a share snapshot while a previous Snapshot Share operation is in progress fails with 409 (Conflict).
func (client Client) CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "CreateSnapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreateSnapshotPreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.CreateSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure sending request")
return
}
result, err = client.CreateSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure responding to request")
return
}
return
}
// CreateSnapshotPreparer prepares the CreateSnapshot request.
func (client Client) CreateSnapshotPreparer(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSnapshotSender sends the CreateSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateSnapshotResponder handles the response to the CreateSnapshot request. The method always
// closes the http.Response Body.
func (client Client) CreateSnapshotResponder(resp *http.Response) (result CreateSnapshotResult, err error) {
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/snapshot_delete.go 0000664 0000000 0000000 00000006552 14232154237 0024035 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// DeleteSnapshot deletes the specified Snapshot of a Storage Share
func (client Client) DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` must be a lower-cased string.")
}
if shareSnapshot == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareSnapshot` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, shareName, shareSnapshot)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, shareName string, shareSnapshot string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
"sharesnapshot": autorest.Encode("query", shareSnapshot),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/snapshot_get.go 0000664 0000000 0000000 00000007101 14232154237 0023341 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetSnapshotPropertiesResult struct {
autorest.Response
MetaData map[string]string
}
// GetSnapshot gets information about the specified Snapshot of the specified Storage Share
func (client Client) GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` must be a lower-cased string.")
}
if snapshotShare == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`snapshotShare` cannot be an empty string.")
}
req, err := client.GetSnapshotPreparer(ctx, accountName, shareName, snapshotShare)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.GetSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure sending request")
return
}
result, err = client.GetSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPreparer(ctx context.Context, accountName, shareName, snapshotShare string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"snapshot": autorest.Encode("query", snapshotShare),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSnapshotSender sends the GetSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetSnapshotResponder handles the response to the GetSnapshot request. The method always
// closes the http.Response Body.
func (client Client) GetSnapshotResponder(resp *http.Response) (result GetSnapshotPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/stats.go 0000664 0000000 0000000 00000006470 14232154237 0022011 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetStatsResult struct {
autorest.Response
// The approximate size of the data stored on the share.
// Note that this value may not include all recently created or recently resized files.
ShareUsageBytes int64 `xml:"ShareUsageBytes"`
}
// GetStats returns information about the specified Storage Share
func (client Client) GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` must be a lower-cased string.")
}
req, err := client.GetStatsPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", nil, "Failure preparing request")
return
}
resp, err := client.GetStatsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure sending request")
return
}
result, err = client.GetStatsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure responding to request")
return
}
return
}
// GetStatsPreparer prepares the GetStats request.
func (client Client) GetStatsPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "stats"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetStatsSender sends the GetStats request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetStatsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetStatsResponder handles the response to the GetStats request. The method always
// closes the http.Response Body.
func (client Client) GetStatsResponder(resp *http.Response) (result GetStatsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/file/shares/version.go 0000664 0000000 0000000 00000000464 14232154237 0022335 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/queue/ 0000775 0000000 0000000 00000000000 14232154237 0017235 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/queue/messages/ 0000775 0000000 0000000 00000000000 14232154237 0021044 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/queue/messages/README.md 0000664 0000000 0000000 00000002062 14232154237 0022323 0 ustar 00root root 0000000 0000000 ## Queue Storage Messages SDK for API version 2018-11-09
This package allows you to interact with the Messages Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/messages"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
messagesClient := messages.New()
messagesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := messages.PutInput{
Message: "hello",
}
if _, err := messagesClient.Put(ctx, accountName, queueName, input); err != nil {
return fmt.Errorf("Error creating Message: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/queue/messages/api.go 0000664 0000000 0000000 00000001466 14232154237 0022153 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageQueueMessage interface {
Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error)
Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error)
GetResourceID(accountName, queueName, messageID string) string
Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error)
Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error)
Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/client.go 0000664 0000000 0000000 00000001114 14232154237 0022646 0 ustar 00root root 0000000 0000000 package messages
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Messages.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/delete.go 0000664 0000000 0000000 00000006523 14232154237 0022643 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a specific message
func (client Client) Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Delete", "`queueName` must be a lower-cased string.")
}
if messageID == "" {
return result, validation.NewError("messages.Client", "Delete", "`messageID` cannot be an empty string.")
}
if popReceipt == "" {
return result, validation.NewError("messages.Client", "Delete", "`popReceipt` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName, messageID, popReceipt)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, queueName, messageID, popReceipt string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", popReceipt),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/get.go 0000664 0000000 0000000 00000007666 14232154237 0022171 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
// VisibilityTimeout specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
VisibilityTimeout *int
}
// Get retrieves one or more messages from the front of the queue
func (client Client) Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Get", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Get", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Get", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Get", "`numberOfMessages` must be between 1 and 32.")
}
if input.VisibilityTimeout != nil {
t := *input.VisibilityTimeout
maxTime := (time.Hour * 24 * 7).Seconds()
if t < 1 || t < int(maxTime) {
return result, validation.NewError("messages.Client", "Get", "`input.VisibilityTimeout` must be larger than or equal to 1 second, and cannot be larger than 7 days.")
}
}
req, err := client.GetPreparer(ctx, accountName, queueName, numberOfMessages, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("query", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/lifecycle_test.go 0000664 0000000 0000000 00000005565 14232154237 0024404 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageQueueMessage = Client{}
func TestLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := queues.NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
messagesClient := NewWithEnvironment(client.Environment)
messagesClient.Client = client.PrepareWithAuthorizer(messagesClient.Client, storageAuth)
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error creating queue: %s", err)
}
defer queuesClient.Delete(ctx, accountName, queueName)
input := PutInput{
Message: "ohhai",
}
putResp, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message in queue: %s", err)
}
messageId := (*putResp.QueueMessages)[0].MessageId
popReceipt := (*putResp.QueueMessages)[0].PopReceipt
_, err = messagesClient.Update(ctx, accountName, queueName, messageId, UpdateInput{
PopReceipt: popReceipt,
Message: "Updated message",
VisibilityTimeout: 65,
})
if err != nil {
t.Fatalf("Error updating: %s", err)
}
for i := 0; i < 5; i++ {
input := PutInput{
Message: fmt.Sprintf("Message %d", i),
}
_, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message %d in queue: %s", i, err)
}
}
peakedMessages, err := messagesClient.Peek(ctx, accountName, queueName, 3)
if err != nil {
t.Fatalf("Error peaking messages: %s", err)
}
for _, v := range *peakedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
}
retrievedMessages, err := messagesClient.Get(ctx, accountName, queueName, 6, GetInput{})
if err != nil {
t.Fatalf("Error retrieving messages: %s", err)
}
for _, v := range *retrievedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
_, err = messagesClient.Delete(ctx, accountName, queueName, v.MessageId, v.PopReceipt)
if err != nil {
t.Fatalf("Error deleting message from queue: %s", err)
}
}
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/models.go 0000664 0000000 0000000 00000001010 14232154237 0022646 0 ustar 00root root 0000000 0000000 package messages
import "github.com/Azure/go-autorest/autorest"
type QueueMessage struct {
MessageText string `xml:"MessageText"`
}
type QueueMessagesListResult struct {
autorest.Response
QueueMessages *[]QueueMessageResponse `xml:"QueueMessage"`
}
type QueueMessageResponse struct {
MessageId string `xml:"MessageId"`
InsertionTime string `xml:"InsertionTime"`
ExpirationTime string `xml:"ExpirationTime"`
PopReceipt string `xml:"PopReceipt"`
TimeNextVisible string `xml:"TimeNextVisible"`
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/peek.go 0000664 0000000 0000000 00000006512 14232154237 0022323 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Peek retrieves one or more messages from the front of the queue, but doesn't alter the visibility of the messages
func (client Client) Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Peek", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Peek", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Peek", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Peek", "`numberOfMessages` must be between 1 and 32.")
}
req, err := client.PeekPreparer(ctx, accountName, queueName, numberOfMessages)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", nil, "Failure preparing request")
return
}
resp, err := client.PeekSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure sending request")
return
}
result, err = client.PeekResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure responding to request")
return
}
return
}
// PeekPreparer prepares the Peek request.
func (client Client) PeekPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
"peekonly": autorest.Encode("query", true),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PeekSender sends the Peek request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PeekSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PeekResponder handles the response to the Peek request. The method always
// closes the http.Response Body.
func (client Client) PeekResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/put.go 0000664 0000000 0000000 00000010107 14232154237 0022202 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// The maximum time-to-live can be any positive number,
// as well as -1 indicating that the message does not expire.
// If this parameter is omitted, the default time-to-live is 7 days.
MessageTtl *int
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// visibilitytimeout should be set to a value smaller than the time-to-live value.
// If not specified, the default value is 0.
VisibilityTimeout *int
}
// Put adds a new message to the back of the message queue
func (client Client) Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Put", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Put", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Put", "`queueName` must be a lower-cased string.")
}
req, err := client.PutPreparer(ctx, accountName, queueName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", nil, "Failure preparing request")
return
}
resp, err := client.PutSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure sending request")
return
}
result, err = client.PutResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure responding to request")
return
}
return
}
// PutPreparer prepares the Put request.
func (client Client) PutPreparer(ctx context.Context, accountName, queueName string, input PutInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{}
if input.MessageTtl != nil {
queryParameters["messagettl"] = autorest.Encode("path", *input.MessageTtl)
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("path", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutSender sends the Put request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutResponder handles the response to the Put request. The method always
// closes the http.Response Body.
func (client Client) PutResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/resource_id.go 0000664 0000000 0000000 00000003044 14232154237 0023677 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Message within a Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName, messageID string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/messages/%s", domain, queueName, messageID)
}
type ResourceID struct {
AccountName string
QueueName string
MessageID string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Message within a Queue
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) != 3 {
return nil, fmt.Errorf("Expected the path to contain 3 segments but got %d", len(segments))
}
queueName := segments[0]
messageID := segments[2]
return &ResourceID{
AccountName: *accountName,
MessageID: messageID,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/resource_id_test.go 0000664 0000000 0000000 00000004321 14232154237 0024735 0 ustar 00root root 0000000 0000000 package messages
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1", "message1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected Queue Name to be `queue1` but got %q", actual.QueueName)
}
if actual.MessageID != "message1" {
t.Fatalf("Expected Message ID to be `message1` but got %q", actual.MessageID)
}
}
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/update.go 0000664 0000000 0000000 00000010071 14232154237 0022654 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type UpdateInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// Specifies the valid pop receipt value required to modify this message.
PopReceipt string
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// A message can be updated until it has been deleted or has expired.
VisibilityTimeout int
}
// Update updates an existing message based on it's Pop Receipt
func (client Client) Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Update", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Update", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Update", "`queueName` must be a lower-cased string.")
}
if input.PopReceipt == "" {
return result, validation.NewError("messages.Client", "Update", "`input.PopReceipt` cannot be an empty string.")
}
req, err := client.UpdatePreparer(ctx, accountName, queueName, messageID, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", nil, "Failure preparing request")
return
}
resp, err := client.UpdateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure sending request")
return
}
result, err = client.UpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure responding to request")
return
}
return
}
// UpdatePreparer prepares the Update request.
func (client Client) UpdatePreparer(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", input.PopReceipt),
"visibilitytimeout": autorest.Encode("query", input.VisibilityTimeout),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UpdateSender sends the Update request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UpdateResponder handles the response to the Update request. The method always
// closes the http.Response Body.
func (client Client) UpdateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/messages/version.go 0000664 0000000 0000000 00000000466 14232154237 0023066 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/ 0000775 0000000 0000000 00000000000 14232154237 0020544 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/queue/queues/README.md 0000664 0000000 0000000 00000002013 14232154237 0022017 0 ustar 00root root 0000000 0000000 ## Queue Storage Queues SDK for API version 2018-11-09
This package allows you to interact with the Queues Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
queuesClient := queues.New()
queuesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := queuesClient.Create(ctx, accountName, queueName, metadata); err != nil {
return fmt.Errorf("Error creating Queue: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/queue/queues/api.go 0000664 0000000 0000000 00000001556 14232154237 0021653 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageQueue interface {
Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error)
SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error)
GetResourceID(accountName, queueName string) string
SetServiceProperties(ctx context.Context, accountName string, properties StorageServiceProperties) (result autorest.Response, err error)
GetServiceProperties(ctx context.Context, accountName string) (result StorageServicePropertiesResponse, err error)
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/client.go 0000664 0000000 0000000 00000001126 14232154237 0022351 0 ustar 00root root 0000000 0000000 package queues
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Queue Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/create.go 0000664 0000000 0000000 00000006247 14232154237 0022347 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates the specified Queue within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Create", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Create", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Create", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/delete.go 0000664 0000000 0000000 00000005502 14232154237 0022337 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Queue within the specified Storage Account
func (client Client) Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Delete", "`queueName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/lifecycle_test.go 0000664 0000000 0000000 00000014166 14232154237 0024101 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageQueue = Client{}
func TestQueuesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
_, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
// first let's test an empty container
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
// then let's retrieve it to ensure there's no metadata..
resp, err := queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// then let's add some..
updatedMetaData := map[string]string{
"band": "panic",
"boots": "the-overpass",
}
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, updatedMetaData)
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error re-retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 2 {
t.Fatalf("Expected metadata to have 2 items but got: %s", resp.MetaData)
}
if resp.MetaData["band"] != "panic" {
t.Fatalf("Expected `band` to be `panic` but got: %s", resp.MetaData["band"])
}
if resp.MetaData["boots"] != "the-overpass" {
t.Fatalf("Expected `boots` to be `the-overpass` but got: %s", resp.MetaData["boots"])
}
// and woo let's remove it again
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// set some properties
props := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "GET,PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
CorsRule{
AllowedMethods: "POST",
AllowedOrigins: "http://www.test.com",
ExposedHeaders: "*",
AllowedHeaders: "x-method-*",
MaxAgeInSeconds: 200,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err := queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) > 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "GET,PUT" {
t.Fatalf("CORS Methods weren't set!")
}
if properties.Cors.CorsRule[1].AllowedMethods != "POST" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
includeAPIS := true
// set some properties
props2 := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
IncludeAPIs: &includeAPIS,
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props2)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err = queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) == 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "PUT" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if !properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
log.Printf("[DEBUG] Deleting..")
_, err = queuesClient.Delete(ctx, accountName, queueName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/metadata_get.go 0000664 0000000 0000000 00000006376 14232154237 0023526 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the metadata for this Queue
func (client Client) GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/metadata_set.go 0000664 0000000 0000000 00000006576 14232154237 0023544 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData returns the metadata for this Queue
func (client Client) SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/models.go 0000664 0000000 0000000 00000002410 14232154237 0022353 0 ustar 00root root 0000000 0000000 package queues
type StorageServiceProperties struct {
Logging *LoggingConfig `xml:"Logging,omitempty"`
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
Cors *Cors `xml:"Cors,omitempty"`
}
type LoggingConfig struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
}
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
// Element IncludeAPIs is only expected when Metrics is enabled
IncludeAPIs *bool `xml:"IncludeAPIs,omitempty"`
}
type RetentionPolicy struct {
Enabled bool `xml:"Enabled"`
Days int `xml:"Days,omitempty"`
}
type Cors struct {
CorsRule []CorsRule `xml:"CorsRule"`
}
type CorsRule struct {
AllowedOrigins string `xml:"AllowedOrigins"`
AllowedMethods string `xml:"AllowedMethods"`
AllowedHeaders string `xml:"AllowedHeaders`
ExposedHeaders string `xml:"ExposedHeaders"`
MaxAgeInSeconds int `xml:"MaxAgeInSeconds"`
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/properties_get.go 0000664 0000000 0000000 00000005670 14232154237 0024136 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type StorageServicePropertiesResponse struct {
StorageServiceProperties
autorest.Response
}
// SetServiceProperties gets the properties for this queue
func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result StorageServicePropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.GetServicePropertiesPreparer(ctx, accountName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.GetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// GetServicePropertiesPreparer prepares the GetServiceProperties request.
func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetServicePropertiesSender sends the GetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetServicePropertiesResponder handles the response to the GetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) GetServicePropertiesResponder(resp *http.Response) (result StorageServicePropertiesResponse, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/properties_set.go 0000664 0000000 0000000 00000005575 14232154237 0024156 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetServiceProperties sets the properties for this queue
func (client Client) SetServiceProperties(ctx context.Context, accountName string, properties StorageServiceProperties) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.SetServicePropertiesPreparer(ctx, accountName, properties)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetServicePropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.SetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// SetServicePropertiesPreparer prepares the SetServiceProperties request.
func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, properties StorageServiceProperties) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(properties),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) SetServicePropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/resource_id.go 0000664 0000000 0000000 00000002315 14232154237 0023377 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, queueName)
}
type ResourceID struct {
AccountName string
QueueName string
}
// ParseResourceID parses the Resource ID and returns an Object which
// can be used to interact with a Queue within a Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.queue.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
queueName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/resource_id_test.go 0000664 0000000 0000000 00000003701 14232154237 0024436 0 ustar 00root root 0000000 0000000 package queues
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected the queue name to be `queue1` but got %q", actual.QueueName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/queue/queues/version.go 0000664 0000000 0000000 00000000464 14232154237 0022564 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/table/ 0000775 0000000 0000000 00000000000 14232154237 0017200 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/table/entities/ 0000775 0000000 0000000 00000000000 14232154237 0021024 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/table/entities/README.md 0000664 0000000 0000000 00000002166 14232154237 0022310 0 ustar 00root root 0000000 0000000 ## Table Storage Entities SDK for API version 2018-11-09
This package allows you to interact with the Entities Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/table/entities"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
entitiesClient := entities.New()
entitiesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := entities.InsertEntityInput{
PartitionKey: "abc",
RowKey: "123",
MetaDataLevel: entities.NoMetaData,
Entity: map[string]interface{}{
"title": "Don't Kill My Vibe",
"artist": "Sigrid",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, input); err != nil {
return fmt.Errorf("Error creating Entity: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/table/entities/api.go 0000664 0000000 0000000 00000001700 14232154237 0022122 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageTableEntity interface {
Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error)
Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error)
InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error)
InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error)
Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error)
Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error)
GetResourceID(accountName, tableName, partitionKey, rowKey string) string
}
giovanni-0.20.0/storage/2018-11-09/table/entities/client.go 0000664 0000000 0000000 00000001130 14232154237 0022624 0 ustar 00root root 0000000 0000000 package entities
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/table/entities/delete.go 0000664 0000000 0000000 00000007327 14232154237 0022626 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteEntityInput struct {
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Delete deletes an existing entity in a table.
func (client Client) Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Delete", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.RowKey` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
// TODO: support for eTags
"If-Match": "*",
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/entities/get.go 0000664 0000000 0000000 00000007013 14232154237 0022133 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetEntityInput struct {
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
}
type GetEntityResult struct {
autorest.Response
Entity map[string]interface{}
}
// Get queries entities in a table and includes the $filter and $select options.
func (client Client) Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Get", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Get", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.RowKey` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, tableName string, input GetEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetEntityResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result.Entity),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/entities/insert.go 0000664 0000000 0000000 00000010207 14232154237 0022657 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertEntityInput struct {
// The level of MetaData provided for this Entity
MetaDataLevel MetaDataLevel
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Insert inserts a new entity into a table.
func (client Client) Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Insert", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Insert", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", nil, "Failure preparing request")
return
}
resp, err := client.InsertSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure sending request")
return
}
result, err = client.InsertResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure responding to request")
return
}
return
}
// InsertPreparer prepares the Insert request.
func (client Client) InsertPreparer(ctx context.Context, accountName, tableName string, input InsertEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"Prefer": "return-no-content",
}
input.Entity["PartitionKey"] = input.PartitionKey
input.Entity["RowKey"] = input.RowKey
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertSender sends the Insert request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertResponder handles the response to the Insert request. The method always
// closes the http.Response Body.
func (client Client) InsertResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/entities/insert_or_merge.go 0000664 0000000 0000000 00000010625 14232154237 0024542 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrMergeEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrMerge updates an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrMergePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrMergeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure sending request")
return
}
result, err = client.InsertOrMergeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure responding to request")
return
}
return
}
// InsertOrMergePreparer prepares the InsertOrMerge request.
func (client Client) InsertOrMergePreparer(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrMergeSender sends the InsertOrMerge request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrMergeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrMergeResponder handles the response to the InsertOrMerge request. The method always
// closes the http.Response Body.
func (client Client) InsertOrMergeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/entities/insert_or_replace.go 0000664 0000000 0000000 00000010706 14232154237 0025056 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrReplaceEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrReplace replaces an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrReplacePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrReplaceSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure sending request")
return
}
result, err = client.InsertOrReplaceResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure responding to request")
return
}
return
}
// InsertOrReplacePreparer prepares the InsertOrReplace request.
func (client Client) InsertOrReplacePreparer(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrReplaceSender sends the InsertOrReplace request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrReplaceSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrReplaceResponder handles the response to the InsertOrReplace request. The method always
// closes the http.Response Body.
func (client Client) InsertOrReplaceResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/entities/lifecycle_test.go 0000664 0000000 0000000 00000010202 14232154237 0024344 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/table/tables"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageTableEntity = Client{}
func TestEntitiesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := tables.NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
defer tablesClient.Delete(ctx, accountName, tableName)
entitiesClient := NewWithEnvironment(client.Environment)
entitiesClient.Client = client.PrepareWithAuthorizer(entitiesClient.Client, storageAuth)
partitionKey := "hello"
rowKey := "there"
t.Logf("[DEBUG] Inserting..")
insertInput := InsertEntityInput{
MetaDataLevel: NoMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "world",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, insertInput); err != nil {
t.Logf("Error retrieving: %s", err)
}
t.Logf("[DEBUG] Insert or Merging..")
insertOrMergeInput := InsertOrMergeEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "ther88e",
},
}
if _, err := entitiesClient.InsertOrMerge(ctx, accountName, tableName, insertOrMergeInput); err != nil {
t.Logf("Error insert/merging: %s", err)
}
t.Logf("[DEBUG] Insert or Replacing..")
insertOrReplaceInput := InsertOrReplaceEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "pandas",
},
}
if _, err := entitiesClient.InsertOrReplace(ctx, accountName, tableName, insertOrReplaceInput); err != nil {
t.Logf("Error inserting/replacing: %s", err)
}
t.Logf("[DEBUG] Querying..")
queryInput := QueryEntitiesInput{
MetaDataLevel: NoMetaData,
}
results, err := entitiesClient.Query(ctx, accountName, tableName, queryInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
if len(results.Entities) != 1 {
t.Fatalf("Expected 1 item but got %d", len(results.Entities))
}
for _, v := range results.Entities {
thisPartitionKey := v["PartitionKey"].(string)
thisRowKey := v["RowKey"].(string)
if partitionKey != thisPartitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, thisPartitionKey)
}
if rowKey != thisRowKey {
t.Fatalf("Expected Partition Key to be %q but got %q", rowKey, thisRowKey)
}
}
t.Logf("[DEBUG] Retrieving..")
getInput := GetEntityInput{
MetaDataLevel: MinimalMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
}
getResults, err := entitiesClient.Get(ctx, accountName, tableName, getInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
partitionKey2 := getResults.Entity["PartitionKey"].(string)
rowKey2 := getResults.Entity["RowKey"].(string)
if partitionKey2 != partitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, partitionKey2)
}
if rowKey2 != rowKey {
t.Fatalf("Expected Row Key to be %q but got %q", rowKey, rowKey2)
}
t.Logf("[DEBUG] Deleting..")
deleteInput := DeleteEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
}
if _, err := entitiesClient.Delete(ctx, accountName, tableName, deleteInput); err != nil {
t.Logf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2018-11-09/table/entities/models.go 0000664 0000000 0000000 00000000306 14232154237 0022635 0 ustar 00root root 0000000 0000000 package entities
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
giovanni-0.20.0/storage/2018-11-09/table/entities/query.go 0000664 0000000 0000000 00000012065 14232154237 0022524 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type QueryEntitiesInput struct {
// An optional OData filter
Filter *string
// An optional comma-separated
PropertyNamesToSelect *[]string
// An optional OData top
Top *int
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
// The Next Partition Key used to load data from a previous point
NextPartitionKey *string
// The Next Row Key used to load data from a previous point
NextRowKey *string
}
type QueryEntitiesResult struct {
autorest.Response
NextPartitionKey string
NextRowKey string
MetaData string `json:"odata.metadata,omitempty"`
Entities []map[string]interface{} `json:"value"`
}
// Query queries entities in a table and includes the $filter and $select options.
func (client Client) Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Query", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Query", "`tableName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"additionalParameters": "",
}
//PartitionKey='',RowKey=''
additionalParams := make([]string, 0)
if input.PartitionKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("PartitionKey='%s'", input.PartitionKey))
}
if input.RowKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("RowKey='%s'", input.RowKey))
}
if len(additionalParams) > 0 {
pathParameters["additionalParameters"] = autorest.Encode("path", strings.Join(additionalParams, ","))
}
queryParameters := map[string]interface{}{}
if input.Filter != nil {
queryParameters["$filter"] = autorest.Encode("query", *input.Filter)
}
if input.PropertyNamesToSelect != nil {
queryParameters["$select"] = autorest.Encode("query", strings.Join(*input.PropertyNamesToSelect, ","))
}
if input.Top != nil {
queryParameters["$top"] = autorest.Encode("query", *input.Top)
}
if input.NextPartitionKey != nil {
queryParameters["NextPartitionKey"] = *input.NextPartitionKey
}
if input.NextRowKey != nil {
queryParameters["NextRowKey"] = *input.NextRowKey
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
// GET /myaccount/Customers()?$filter=(Rating%20ge%203)%20and%20(Rating%20le%206)&$select=PartitionKey,RowKey,Address,CustomerSince
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}({additionalParameters})", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result QueryEntitiesResult, err error) {
if resp != nil && resp.Header != nil {
result.NextPartitionKey = resp.Header.Get("x-ms-continuation-NextPartitionKey")
result.NextRowKey = resp.Header.Get("x-ms-continuation-NextRowKey")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/entities/resource_id.go 0000664 0000000 0000000 00000005370 14232154237 0023663 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Entity
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName, partitionKey, rowKey string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s(PartitionKey='%s',RowKey='%s')", domain, tableName, partitionKey, rowKey)
}
type ResourceID struct {
AccountName string
TableName string
PartitionKey string
RowKey string
}
// ParseResourceID parses the specified Resource ID and returns an object which
// can be used to look up the specified Entity within the specified Table
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.Contains(uri.Path, "(") || !strings.HasSuffix(uri.Path, ")") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `tables(PartitionKey='',RowKey='')` but got %q", path)
}
// NOTE: honestly this could probably be a RegEx, but this seemed like the simplest way to
// allow these two fields to be specified in either order
indexOfBracket := strings.IndexByte(path, '(')
tableName := path[0:indexOfBracket]
// trim off the brackets
temp := strings.TrimPrefix(path, fmt.Sprintf("%s(", tableName))
temp = strings.TrimSuffix(temp, ")")
dictionary := strings.Split(temp, ",")
partitionKey := ""
rowKey := ""
for _, v := range dictionary {
split := strings.Split(v, "=")
if len(split) != 2 {
return nil, fmt.Errorf("Expected 2 segments but got %d for %q", len(split), v)
}
key := split[0]
value := strings.TrimSuffix(strings.TrimPrefix(split[1], "'"), "'")
if strings.EqualFold(key, "PartitionKey") {
partitionKey = value
} else if strings.EqualFold(key, "RowKey") {
rowKey = value
} else {
return nil, fmt.Errorf("Unexpected Key %q", key)
}
}
if partitionKey == "" {
return nil, fmt.Errorf("Expected a PartitionKey but didn't get one")
}
if rowKey == "" {
return nil, fmt.Errorf("Expected a RowKey but didn't get one")
}
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
PartitionKey: partitionKey,
RowKey: rowKey,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/table/entities/resource_id_test.go 0000664 0000000 0000000 00000005012 14232154237 0024713 0 ustar 00root root 0000000 0000000 package entities
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1", "partition1", "row1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
if actual.PartitionKey != "partition1" {
t.Fatalf("Expected Partition Key to be `partition1` but got %q", actual.PartitionKey)
}
if actual.RowKey != "row1" {
t.Fatalf("Expected Row Key to be `row1` but got %q", actual.RowKey)
}
}
}
giovanni-0.20.0/storage/2018-11-09/table/entities/version.go 0000664 0000000 0000000 00000000466 14232154237 0023046 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2018-11-09/table/tables/ 0000775 0000000 0000000 00000000000 14232154237 0020452 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2018-11-09/table/tables/README.md 0000664 0000000 0000000 00000001550 14232154237 0021732 0 ustar 00root root 0000000 0000000 ## Table Storage Tables SDK for API version 2018-11-09
This package allows you to interact with the Tables Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/table/tables"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
tablesClient := tables.New()
tablesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
if _, err := tablesClient.Insert(ctx, accountName, tableName); err != nil {
return fmt.Errorf("Error creating Table: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2018-11-09/table/tables/acl_get.go 0000664 0000000 0000000 00000005654 14232154237 0022411 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL returns the Access Control List for the specified Table
func (client Client) GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`tableName` cannot be an empty string.")
}
req, err := client.GetACLPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/tables/acl_set.go 0000664 0000000 0000000 00000006062 14232154237 0022417 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"encoding/xml"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List for the specified Table
func (client Client) SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`tableName` cannot be an empty string.")
}
req, err := client.SetACLPreparer(ctx, accountName, tableName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/tables/api.go 0000664 0000000 0000000 00000001417 14232154237 0021555 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageTable interface {
Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error)
Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
GetResourceID(accountName, tableName string) string
Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error)
SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2018-11-09/table/tables/client.go 0000664 0000000 0000000 00000001126 14232154237 0022257 0 ustar 00root root 0000000 0000000 package tables
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2018-11-09/table/tables/create.go 0000664 0000000 0000000 00000005571 14232154237 0022254 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type createTableRequest struct {
TableName string `json:"TableName"`
}
// Create creates a new table in the storage account.
func (client Client) Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Create", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Create", "`tableName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// NOTE: we could support returning metadata here, but it doesn't appear to be directly useful
// vs making a request using the Get methods as-necessary?
"Accept": "application/json;odata=nometadata",
"Prefer": "return-no-content",
}
body := createTableRequest{
TableName: tableName,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithJSON(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/tables/delete.go 0000664 0000000 0000000 00000005260 14232154237 0022246 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified table and any data it contains.
func (client Client) Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Delete", "`tableName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/tables/exists.go 0000664 0000000 0000000 00000005304 14232154237 0022322 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Exists checks that the specified table exists
func (client Client) Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Exists", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Exists", "`tableName` cannot be an empty string.")
}
req, err := client.ExistsPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", nil, "Failure preparing request")
return
}
resp, err := client.ExistsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure sending request")
return
}
result, err = client.ExistsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure responding to request")
return
}
return
}
// ExistsPreparer prepares the Exists request.
func (client Client) ExistsPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.AsContentType("application/xml"),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ExistsSender sends the Exists request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ExistsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ExistsResponder handles the response to the Exists request. The method always
// closes the http.Response Body.
func (client Client) ExistsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/tables/lifecycle_test.go 0000664 0000000 0000000 00000007234 14232154237 0024005 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageTable = Client{}
func TestTablesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
// first look it up directly and confirm it's there
t.Logf("[DEBUG] Checking if Table exists..")
if _, err := tablesClient.Exists(ctx, accountName, tableName); err != nil {
t.Fatalf("Error checking if Table %q exists: %s", tableName, err)
}
// then confirm it exists in the Query too
t.Logf("[DEBUG] Querying for Tables..")
result, err := tablesClient.Query(ctx, accountName, NoMetaData)
if err != nil {
t.Fatalf("Error retrieving Tables: %s", err)
}
found := false
for _, v := range result.Tables {
log.Printf("[DEBUG] Table: %q", v.TableName)
if v.TableName == tableName {
found = true
}
}
if !found {
t.Fatalf("%q was not found in the Query response!", tableName)
}
t.Logf("[DEBUG] Setting ACL's for Table %q..", tableName)
acls := []SignedIdentifier{
{
Id: "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=",
AccessPolicy: AccessPolicy{
Permission: "raud",
Start: "2020-11-26T08:49:37.0000000Z",
Expiry: "2020-11-27T08:49:37.0000000Z",
},
},
}
if _, err := tablesClient.SetACL(ctx, accountName, tableName, acls); err != nil {
t.Fatalf("Error setting ACLs: %s", err)
}
t.Logf("[DEBUG] Retrieving ACL's for Table %q..", tableName)
retrievedACLs, err := tablesClient.GetACL(ctx, accountName, tableName)
if err != nil {
t.Fatalf("Error retrieving ACLs: %s", err)
}
if len(retrievedACLs.SignedIdentifiers) != len(acls) {
t.Fatalf("Expected %d but got %q ACLs", len(retrievedACLs.SignedIdentifiers), len(acls))
}
for i, retrievedAcl := range retrievedACLs.SignedIdentifiers {
expectedAcl := acls[i]
if retrievedAcl.Id != expectedAcl.Id {
t.Fatalf("Expected ID to be %q but got %q", retrievedAcl.Id, expectedAcl.Id)
}
if retrievedAcl.AccessPolicy.Start != expectedAcl.AccessPolicy.Start {
t.Fatalf("Expected Start to be %q but got %q", retrievedAcl.AccessPolicy.Start, expectedAcl.AccessPolicy.Start)
}
if retrievedAcl.AccessPolicy.Expiry != expectedAcl.AccessPolicy.Expiry {
t.Fatalf("Expected Expiry to be %q but got %q", retrievedAcl.AccessPolicy.Expiry, expectedAcl.AccessPolicy.Expiry)
}
if retrievedAcl.AccessPolicy.Permission != expectedAcl.AccessPolicy.Permission {
t.Fatalf("Expected Permission to be %q but got %q", retrievedAcl.AccessPolicy.Permission, expectedAcl.AccessPolicy.Permission)
}
}
t.Logf("[DEBUG] Deleting Table %q..", tableName)
if _, err := tablesClient.Delete(ctx, accountName, tableName); err != nil {
t.Fatalf("Error deleting %q: %s", tableName, err)
}
}
giovanni-0.20.0/storage/2018-11-09/table/tables/models.go 0000664 0000000 0000000 00000001324 14232154237 0022264 0 ustar 00root root 0000000 0000000 package tables
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
type GetResultItem struct {
TableName string `json:"TableName"`
// Optional, depending on the MetaData Level
ODataType string `json:"odata.type,omitempty"`
ODataID string `json:"odata.id,omitEmpty"`
ODataEditLink string `json:"odata.editLink,omitEmpty"`
}
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2018-11-09/table/tables/query.go 0000664 0000000 0000000 00000005430 14232154237 0022150 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetResult struct {
autorest.Response
MetaData string `json:"odata.metadata,omitempty"`
Tables []GetResultItem `json:"value"`
}
// Query returns a list of tables under the specified account.
func (client Client) Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Query", "`accountName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, metaDataLevel)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (*http.Request, error) {
// NOTE: whilst this supports ContinuationTokens and 'Top'
// it appears that 'Skip' returns a '501 Not Implemented'
// as such, we intentionally don't support those right now
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", metaDataLevel),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result GetResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2018-11-09/table/tables/resource_id.go 0000664 0000000 0000000 00000003112 14232154237 0023301 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Table
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/Tables('%s')", domain, tableName)
}
type ResourceID struct {
AccountName string
TableName string
}
// ParseResourceID parses the Resource ID and returns an object which
// can be used to interact with the Table within the specified Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.table.core.windows.net/Table('foo')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.HasPrefix(path, "Tables('") || !strings.HasSuffix(path, "')") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `Tables('name')` but got %q", path)
}
// strip off the `Table('')`
tableName := strings.TrimPrefix(uri.Path, "/Tables('")
tableName = strings.TrimSuffix(tableName, "')")
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
}, nil
}
giovanni-0.20.0/storage/2018-11-09/table/tables/resource_id_test.go 0000664 0000000 0000000 00000004010 14232154237 0024336 0 ustar 00root root 0000000 0000000 package tables
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
}
}
giovanni-0.20.0/storage/2018-11-09/table/tables/version.go 0000664 0000000 0000000 00000000464 14232154237 0022472 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2018-11-09"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/ 0000775 0000000 0000000 00000000000 14232154237 0016105 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/README.md 0000664 0000000 0000000 00000001215 14232154237 0017363 0 ustar 00root root 0000000 0000000 # Storage API Version 2019-12-12
The following API's are supported by this SDK - more information about each SDK can be found within the README in each package.
## Blob Storage
- [Blobs API](blob/blobs)
- [Containers API](blob/containers)
- [Accounts API](blob/accounts)
## DataLakeStore Gen2
- [FileSystems API](datalakestore/filesystems)
- [Paths API](datalakestore/paths)
## File Storage
- [Directories API](file/directories)
- [Files API](file/files)
- [Shares API](file/shares)
## Queue Storage
- [Queues API](queue/queues)
- [Messages API](queue/messages)
## Table Storage
- [Entities API](table/entities)
- [Tables API](table/tables)
giovanni-0.20.0/storage/2019-12-12/blob/ 0000775 0000000 0000000 00000000000 14232154237 0017023 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/blob/accounts/ 0000775 0000000 0000000 00000000000 14232154237 0020642 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/blob/accounts/README.md 0000664 0000000 0000000 00000002463 14232154237 0022126 0 ustar 00root root 0000000 0000000 ## Blob Storage Account SDK for API version 2019-12-12
This package allows you to interact with the Accounts Blob Storage API
### Supported Authorizers
* Azure Active Directory
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/accounts"
)
func Example() error {
accountName := "storageaccount1"
// e.g. https://github.com/tombuildsstuff/giovanni/blob/76f5f686c99ecdcc3fa533a0330d0e1aacb1c327/example/azuread-auth/main.go#L54
client, err := buildClient()
if err != nil {
return fmt.Errorf("error building client: %s", err)
}
ctx := context.TODO()
input := StorageServiceProperties{
StaticWebsite: &StaticWebsite{
Enabled: true,
IndexDocument: index,
ErrorDocument404Path: errorDocument,
},
}
_, err = client.SetServiceProperties(ctx, accountName, input)
if err != nil {
return fmt.Errorf("error setting properties: %s", err)
}
time.Sleep(2 * time.Second)
_, err = accountsClient.GetServiceProperties(ctx, accountName)
if err != nil {
return fmt.Errorf("error getting properties: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/blob/accounts/client.go 0000664 0000000 0000000 00000001122 14232154237 0022443 0 ustar 00root root 0000000 0000000 package accounts
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/blob/accounts/get_service_properties.go 0000664 0000000 0000000 00000005205 14232154237 0025746 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetServicePropertiesResult struct {
autorest.Response
ContentType string
StorageServiceProperties *StorageServiceProperties
}
// GetServicePropertiesPreparer prepares the GetServiceProperties request.
func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) {
queryParameters := map[string]interface{}{
"restype": "service",
"comp": "properties",
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
func (client Client) GetServicePropertiesResponder(resp *http.Response) (result GetServicePropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result.StorageServiceProperties),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result GetServicePropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("accounts.Client", "GetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.GetServicePropertiesPreparer(ctx, accountName)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.GetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure responding to request")
return
}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/accounts/models.go 0000664 0000000 0000000 00000011115 14232154237 0022453 0 ustar 00root root 0000000 0000000 package accounts
import "github.com/Azure/go-autorest/autorest"
type SetServicePropertiesResult struct {
autorest.Response
}
type StorageServiceProperties struct {
// Cors - Specifies CORS rules for the Blob service. You can include up to five CorsRule elements in the request. If no CorsRule elements are included in the request body, all CORS rules will be deleted, and CORS will be disabled for the Blob service.
Cors *CorsRules `xml:"Cors,omitempty"`
// DefaultServiceVersion - DefaultServiceVersion indicates the default version to use for requests to the Blob service if an incoming request’s version is not specified. Possible values include version 2008-10-27 and all more recent versions.
DefaultServiceVersion *string `xml:"DefaultServiceVersion,omitempty"`
// DeleteRetentionPolicy - The blob service properties for soft delete.
DeleteRetentionPolicy *DeleteRetentionPolicy `xml:"DeleteRetentionPolicy,omitempty"`
// Logging - The blob service properties for logging access
Logging *Logging `xml:"Logging,omitempty"`
// HourMetrics - The blob service properties for hour metrics
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
// HourMetrics - The blob service properties for minute metrics
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
// StaticWebsite - Optional
StaticWebsite *StaticWebsite `xml:"StaticWebsite,omitempty"`
}
// StaticWebsite sets the static website support properties on the Blob service.
type StaticWebsite struct {
// Enabled - Required. Indicates whether static website support is enabled for the given account.
Enabled bool `xml:"Enabled"`
// IndexDocument - Optional. The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive.
IndexDocument string `xml:"IndexDocument,omitempty"`
// ErrorDocument404Path - Optional. The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive.
ErrorDocument404Path string `xml:"ErrorDocument404Path,omitempty"`
}
// CorsRules sets the CORS rules. You can include up to five CorsRule elements in the request.
type CorsRules struct {
// CorsRules - The List of CORS rules. You can include up to five CorsRule elements in the request.
CorsRules []CorsRule `xml:"CorsRules,omitempty"`
}
// DeleteRetentionPolicy the blob service properties for soft delete.
type DeleteRetentionPolicy struct {
// Enabled - Indicates whether DeleteRetentionPolicy is enabled for the Blob service.
Enabled bool `xml:"Enabled,omitempty"`
// Days - Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365.
Days int32 `xml:"Days,omitempty"`
}
// CorsRule specifies a CORS rule for the Blob service.
type CorsRule struct {
// AllowedOrigins - Required if CorsRule element is present. A list of origin domains that will be allowed via CORS, or "" to allow all domains
AllowedOrigins []string `xml:"AllowedOrigins,omitempty"`
// AllowedMethods - Required if CorsRule element is present. A list of HTTP methods that are allowed to be executed by the origin.
AllowedMethods []string `xml:"AllowedMethods,omitempty"`
// MaxAgeInSeconds - Required if CorsRule element is present. The number of seconds that the client/browser should cache a preflight response.
MaxAgeInSeconds int32 `xml:"MaxAgeInSeconds,omitempty"`
// ExposedHeaders - Required if CorsRule element is present. A list of response headers to expose to CORS clients.
ExposedHeaders []string `xml:"ExposedHeaders,omitempty"`
// AllowedHeaders - Required if CorsRule element is present. A list of headers allowed to be part of the cross-origin request.
AllowedHeaders []string `xml:"AllowedHeaders,omitempty"`
}
// Logging specifies the access logging options for the Blob service.
type Logging struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy DeleteRetentionPolicy `xml:"RetentionPolicy"`
}
// MetricsConfig specifies the hour and/or minute metrics options for the Blob service.
// Elements are all expected
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy DeleteRetentionPolicy `xml:"RetentionPolicy"`
IncludeAPIs bool `xml:"IncludeAPIs"`
}
giovanni-0.20.0/storage/2019-12-12/blob/accounts/set_service_properties.go 0000664 0000000 0000000 00000005322 14232154237 0025762 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetServicePropertiesPreparer prepares the SetServiceProperties request.
func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, input StorageServiceProperties) (*http.Request, error) {
queryParameters := map[string]interface{}{
"restype": "service",
"comp": "properties",
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithHeaders(headers),
autorest.WithXML(input),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) SetServicePropertiesResponder(resp *http.Response) (result SetServicePropertiesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
func (client Client) SetServiceProperties(ctx context.Context, accountName string, input StorageServiceProperties) (result SetServicePropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("accounts.Client", "SetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.SetServicePropertiesPreparer(ctx, accountName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.SetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure responding to request")
return
}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/accounts/set_service_properties_test.go 0000664 0000000 0000000 00000005316 14232154237 0027024 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
_, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
accountsClient := NewWithEnvironment(client.Environment)
accountsClient.Client = client.PrepareWithStorageResourceManagerAuth(accountsClient.Client)
input := StorageServiceProperties{}
_, err = accountsClient.SetServiceProperties(ctx, accountName, input)
if err != nil {
t.Fatal(fmt.Errorf("error setting properties: %s", err))
}
var index = "index.html"
//var enabled = true
var errorDocument = "404.html"
input = StorageServiceProperties{
StaticWebsite: &StaticWebsite{
Enabled: true,
IndexDocument: index,
ErrorDocument404Path: errorDocument,
},
Logging: &Logging{
Version: "2.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: DeleteRetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = accountsClient.SetServiceProperties(ctx, accountName, input)
if err != nil {
t.Fatal(fmt.Errorf("error setting properties: %s", err))
}
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
result, err := accountsClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatal(fmt.Errorf("error getting properties: %s", err))
}
website := result.StorageServiceProperties.StaticWebsite
if website.Enabled != true {
t.Fatalf("Expected the StaticWebsite %t but got %t", true, website.Enabled)
}
logging := result.StorageServiceProperties.Logging
if logging.Version != "2.0" {
t.Fatalf("Expected the Logging Version %s but got %s", "2.0", logging.Version)
}
if !logging.Read {
t.Fatalf("Expected the Logging Read %t but got %t", true, logging.Read)
}
if !logging.Write {
t.Fatalf("Expected the Logging Write %t but got %t", true, logging.Write)
}
if !logging.Delete {
t.Fatalf("Expected the Logging Delete %t but got %t", true, logging.Delete)
}
if !logging.RetentionPolicy.Enabled {
t.Fatalf("Expected the Logging RetentionPolicy.Enabled %t but got %t", true, logging.RetentionPolicy.Enabled)
}
if logging.RetentionPolicy.Days != 7 {
t.Fatalf("Expected the Logging RetentionPolicy.Enabled %d but got %d", 7, logging.RetentionPolicy.Days)
}
}
giovanni-0.20.0/storage/2019-12-12/blob/accounts/version.go 0000664 0000000 0000000 00000000466 14232154237 0022664 0 ustar 00root root 0000000 0000000 package accounts
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/ 0000775 0000000 0000000 00000000000 14232154237 0020124 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/blob/blobs/README.md 0000664 0000000 0000000 00000002263 14232154237 0021406 0 ustar 00root root 0000000 0000000 ## Blob Storage Blobs SDK for API version 2019-12-12
This package allows you to interact with the Blobs Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/blobs"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
fileName := "example-large-file.iso"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
blobClient := blobs.New()
blobClient.Client.Authorizer = storageAuth
ctx := context.TODO()
copyInput := blobs.CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/blob/blobs/api.go 0000664 0000000 0000000 00000011051 14232154237 0021222 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
)
type StorageBlob interface {
AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error)
Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error)
AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error)
CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error
Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error)
DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error)
DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error)
Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error)
GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error)
GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error)
IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error)
AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error)
BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error)
ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error)
ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error)
RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error)
SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error)
GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error)
SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error)
PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error)
PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error)
PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error)
PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error
PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error)
PutBlockFromURL(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (result PutBlockFromURLResult, err error)
PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error)
PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error)
PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error)
GetResourceID(accountName, containerName, blobName string) string
SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error)
Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error)
GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error)
Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/append_block.go 0000664 0000000 0000000 00000014462 14232154237 0023103 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AppendBlockInput struct {
// 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 an AppendPositionConditionNotMet
// error (HTTP status code 412 – Precondition Failed)
BlobConditionAppendPosition *int64
// 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
// an MaxBlobSizeConditionNotMet error (HTTP status code 412 – Precondition Failed).
BlobConditionMaxSize *int64
// The Bytes which should be appended to the end of this Append Blob.
// This can either be nil, which creates an empty blob, or a byte array
Content *[]byte
// An MD5 hash of the block content.
// This hash is used to verify the integrity of the block during transport.
// When this header is specified, the storage service compares the hash of the content
// that has arrived with this header value.
//
// Note that this MD5 hash is not stored with the blob.
// If the two hashes do not match, the operation will fail with error code 400 (Bad Request).
ContentMD5 *string
// Required if the blob has an active lease.
// To perform this operation on a blob with an active lease, specify the valid lease ID for this header.
LeaseID *string
}
type AppendBlockResult struct {
autorest.Response
BlobAppendOffset string
BlobCommittedBlockCount int64
ContentMD5 string
ETag string
LastModified string
}
// AppendBlock commits a new block of data to the end of an existing append blob.
func (client Client) AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) > (4*1024*1024) {
return result, validation.NewError("files.Client", "PutByteRange", "`input.Content` must be at most 4MB.")
}
req, err := client.AppendBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", nil, "Failure preparing request")
return
}
resp, err := client.AppendBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure sending request")
return
}
result, err = client.AppendBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure responding to request")
return
}
return
}
// AppendBlockPreparer prepares the AppendBlock request.
func (client Client) AppendBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "appendblock"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.BlobConditionAppendPosition != nil {
headers["x-ms-blob-condition-appendpos"] = *input.BlobConditionAppendPosition
}
if input.BlobConditionMaxSize != nil {
headers["x-ms-blob-condition-maxsize"] = *input.BlobConditionMaxSize
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AppendBlockSender sends the AppendBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AppendBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AppendBlockResponder handles the response to the AppendBlock request. The method always
// closes the http.Response Body.
func (client Client) AppendBlockResponder(resp *http.Response) (result AppendBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobAppendOffset = resp.Header.Get("x-ms-blob-append-offset")
result.ContentMD5 = resp.Header.Get("ETag")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
if v := resp.Header.Get("x-ms-blob-committed-block-count"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
result.BlobCommittedBlockCount = int64(i)
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/blob_append_test.go 0000664 0000000 0000000 00000011330 14232154237 0023755 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestAppendBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Append Blob..")
if _, err := blobClient.PutAppendBlob(ctx, accountName, containerName, fileName, PutAppendBlobInput{}); err != nil {
t.Fatalf("Error putting append blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 0 {
t.Fatalf("Expected Content-Length to be 0 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending First Block..")
appendInput := AppendBlockInput{
Content: &[]byte{
12,
48,
93,
76,
29,
10,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending first block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 6 {
t.Fatalf("Expected Content-Length to be 6 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending Second Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
92,
62,
64,
47,
83,
77,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Second block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 12 {
t.Fatalf("Expected Content-Length to be 12 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Acquiring Lease..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error acquiring Lease: %s", err)
}
t.Logf("[DEBUG] Lease ID is %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Appending Third Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
64,
35,
28,
93,
11,
23,
},
LeaseID: &leaseDetails.LeaseID,
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Third block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 18 {
t.Fatalf("Expected Content-Length to be 18 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Breaking Lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseDetails.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
t.Logf("[DEBUG] Deleting Lease..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/blob_page_test.go 0000664 0000000 0000000 00000005541 14232154237 0023431 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPageBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Page Blob..")
fileSize := int64(10240000)
if _, err := blobClient.PutPageBlob(ctx, accountName, containerName, fileName, PutPageBlobInput{
BlobContentLengthBytes: fileSize,
}); err != nil {
t.Fatalf("Error putting page blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != fileSize {
t.Fatalf("Expected Content-Length to be %d but it was %d", fileSize, props.ContentLength)
}
for iteration := 1; iteration <= 3; iteration++ {
t.Logf("[DEBUG] Putting Page %d of 3..", iteration)
byteArray := func() []byte {
o := make([]byte, 0)
for i := 0; i < 512; i++ {
o = append(o, byte(i))
}
return o
}()
startByte := int64(512 * iteration)
endByte := int64(startByte + 511)
putPageInput := PutPageUpdateInput{
StartByte: startByte,
EndByte: endByte,
Content: byteArray,
}
if _, err := blobClient.PutPageUpdate(ctx, accountName, containerName, fileName, putPageInput); err != nil {
t.Fatalf("Error putting page: %s", err)
}
}
t.Logf("[DEBUG] Deleting..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/client.go 0000664 0000000 0000000 00000001117 14232154237 0021731 0 ustar 00root root 0000000 0000000 package blobs
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/copy.go 0000664 0000000 0000000 00000022706 14232154237 0021434 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the name of the source blob or file.
// Beginning with version 2012-02-12, this value may be a URL of up to 2 KB in length that specifies a blob.
// The value should be URL-encoded as it would appear in a request URI.
// A source blob in the same storage account can be authenticated via Shared Key.
// However, if the source is a blob in another account,
// the source blob must either be public or must be authenticated via a shared access signature.
// If the source blob is public, no authentication is required to perform the copy operation.
//
// Beginning with version 2015-02-21, the source object may be a file in the Azure File service.
// If the source object is a file that is to be copied to a blob, then the source file must be authenticated
// using a shared access signature, whether it resides in the same account or in a different account.
//
// Only storage accounts created on or after June 7th, 2012 allow the Copy Blob operation to
// copy from another storage account.
CopySource string
// The ID of the Lease
// Required if the destination blob has an active lease.
// The lease ID specified for this header must match the lease ID of the destination blob.
// If the request does not include the lease ID or it is not valid,
// the operation fails with status code 412 (Precondition Failed).
//
// If this header is specified and the destination blob does not currently have an active lease,
// the operation will also fail with status code 412 (Precondition Failed).
LeaseID *string
// The ID of the Lease on the Source Blob
// Specify to perform the Copy Blob operation only if the lease ID matches the active lease ID of the source blob.
SourceLeaseID *string
// For page blobs on a premium account only. Specifies the tier to be set on the target blob
AccessTier *AccessTier
// 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.
MetaData map[string]string
// An ETag value.
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value matches the ETag value for an existing destination blob.
// If the ETag for the destination blob does not match the ETag specified for If-Match,
// the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value, or the wildcard character (*).
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value does not match the ETag value for the destination blob.
// Specify the wildcard character (*) to perform the operation only if the destination blob does not exist.
// If the specified condition isn't met, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has been modified since the specified date/time.
// If the destination blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has not been modified since the specified date/time.
// If the destination blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value.
// Specify this conditional header to copy the source blob only if its ETag matches the value specified.
// If the ETag values do not match, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfMatch *string
// An ETag value.
// Specify this conditional header to copy the blob only if its ETag does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has been modified
// since the specified date/time.
// If the source blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has not been modified
// since the specified date/time.
// If the source blob has been modified, the Blob service returns status code 412 (Precondition Failed).
// This header cannot be specified if the source is an Azure File.
SourceIfUnmodifiedSince *string
}
type CopyResult struct {
autorest.Response
CopyID string
CopyStatus string
}
// Copy copies a blob to a destination within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
req, err := client.CopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": autorest.Encode("header", input.CopySource),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SourceLeaseID != nil {
headers["x-ms-source-lease-id"] = *input.SourceLeaseID
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.SourceIfMatch != nil {
headers["x-ms-source-if-match"] = *input.SourceIfMatch
}
if input.SourceIfNoneMatch != nil {
headers["x-ms-source-if-none-match"] = *input.SourceIfNoneMatch
}
if input.SourceIfModifiedSince != nil {
headers["x-ms-source-if-modified-since"] = *input.SourceIfModifiedSince
}
if input.SourceIfUnmodifiedSince != nil {
headers["x-ms-source-if-unmodified-since"] = *input.SourceIfUnmodifiedSince
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/copy_abort.go 0000664 0000000 0000000 00000007451 14232154237 0022623 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AbortCopyInput struct {
// The Copy ID which should be aborted
CopyID string
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// AbortCopy aborts a pending Copy Blob operation, and leaves a destination blob with zero length and full metadata.
func (client Client) AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`blobName` cannot be an empty string.")
}
if input.CopyID == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`input.CopyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", input.CopyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/copy_and_wait.go 0000664 0000000 0000000 00000002050 14232154237 0023270 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"time"
)
// CopyAndWait copies a blob to a destination within the storage account and waits for it to finish copying.
func (client Client) CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error {
if _, err := client.Copy(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
for true {
getInput := GetPropertiesInput{
LeaseID: input.LeaseID,
}
getResult, err := client.GetProperties(ctx, accountName, containerName, blobName, getInput)
if err != nil {
return fmt.Errorf("")
}
switch getResult.CopyStatus {
case Aborted:
return fmt.Errorf("Copy was aborted: %s", getResult.CopyStatusDescription)
case Failed:
return fmt.Errorf("Copy failed: %s", getResult.CopyStatusDescription)
case Success:
return nil
case Pending:
time.Sleep(pollingInterval)
continue
}
}
return fmt.Errorf("Unexpected error waiting for the copy to complete")
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/copy_test.go 0000664 0000000 0000000 00000012644 14232154237 0022473 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCopyFromExistingFile(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
copiedFileName := "copied.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Duplicating that file..")
copiedInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetBlobEndpoint(blobClient.BaseURI, accountName), containerName, fileName),
}
if err := blobClient.CopyAndWait(ctx, accountName, containerName, copiedFileName, copiedInput, refreshInterval); err != nil {
t.Fatalf("Error duplicating file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Original File..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the original file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Copied File..")
copiedProps, err := blobClient.GetProperties(ctx, accountName, containerName, copiedFileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the copied file: %s", err)
}
if props.ContentLength != copiedProps.ContentLength {
t.Fatalf("Expected the content length to be %d but it was %d", props.ContentLength, copiedProps.ContentLength)
}
t.Logf("[DEBUG] Deleting copied file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, copiedFileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
t.Logf("[DEBUG] Deleting original file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
func TestCopyFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
if props.ContentLength == 0 {
t.Fatalf("Expected the file to be there but looks like it isn't: %d", props.ContentLength)
}
t.Logf("[DEBUG] Deleting file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/delete.go 0000664 0000000 0000000 00000007057 14232154237 0021726 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteInput struct {
// Should any Snapshots for this Blob also be deleted?
// If the Blob has Snapshots and this is set to False a 409 Conflict will be returned
DeleteSnapshots bool
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// Delete marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`blobName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.DeleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/delete_snapshot.go 0000664 0000000 0000000 00000007675 14232154237 0023653 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The DateTime of the Snapshot which should be marked for Deletion
SnapshotDateTime string
}
// DeleteSnapshot marks a single Snapshot of a Blob for Deletion based on it's DateTime, which will be deleted during the next Garbage Collection cycle.
func (client Client) DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`blobName` cannot be an empty string.")
}
if input.SnapshotDateTime == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`input.SnapshotDateTime` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotDateTime),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/delete_snapshots.go 0000664 0000000 0000000 00000007161 14232154237 0024024 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotsInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// DeleteSnapshots marks all Snapshots of a Blob for Deletion, which will be deleted during the next Garbage Collection Cycle.
func (client Client) DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`blobName` cannot be an empty string.")
}
req, err := client.DeleteSnapshotsPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotsPreparer prepares the DeleteSnapshots request.
func (client Client) DeleteSnapshotsPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// only delete the snapshots but leave the blob as-is
"x-ms-delete-snapshots": "only",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotsSender sends the DeleteSnapshots request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotsResponder handles the response to the DeleteSnapshots request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/get.go 0000664 0000000 0000000 00000007611 14232154237 0021237 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetResult struct {
autorest.Response
Contents []byte
}
// Get reads or downloads a blob from the system, including its metadata and properties.
func (client Client) Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Get", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Get", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Get", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Get", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "Get", "`input.LeaseID` should either be specified or nil, not an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "Get", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, containerName, blobName string, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && int(resp.ContentLength) > 0 {
result.Contents = make([]byte, resp.ContentLength)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/get_block_list.go 0000664 0000000 0000000 00000010765 14232154237 0023450 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetBlockListInput struct {
BlockListType BlockListType
LeaseID *string
}
type GetBlockListResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
// A list of blocks which have been committed
CommittedBlocks CommittedBlocks `xml:"CommittedBlocks,omitempty"`
// A list of blocks which have not yet been committed
UncommittedBlocks UncommittedBlocks `xml:"UncommittedBlocks,omitempty"`
}
// GetBlockList retrieves the list of blocks that have been uploaded as part of a block blob.
func (client Client) GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.GetBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", nil, "Failure preparing request")
return
}
resp, err := client.GetBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure sending request")
return
}
result, err = client.GetBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure responding to request")
return
}
return
}
// GetBlockListPreparer prepares the GetBlockList request.
func (client Client) GetBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"blocklisttype": autorest.Encode("query", string(input.BlockListType)),
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetBlockListSender sends the GetBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetBlockListResponder handles the response to the GetBlockList request. The method always
// closes the http.Response Body.
func (client Client) GetBlockListResponder(resp *http.Response) (result GetBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/get_page_ranges.go 0000664 0000000 0000000 00000011500 14232154237 0023562 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPageRangesInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetPageRangesResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
PageRanges []PageRange `xml:"PageRange"`
}
type PageRange struct {
// The start byte offset for this range, inclusive
Start int64 `xml:"Start"`
// The end byte offset for this range, inclusive
End int64 `xml:"End"`
}
// GetPageRanges returns the list of valid page ranges for a page blob or snapshot of a page blob.
func (client Client) GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`blobName` cannot be an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPageRangesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", nil, "Failure preparing request")
return
}
resp, err := client.GetPageRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure sending request")
return
}
result, err = client.GetPageRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure responding to request")
return
}
return
}
// GetPageRangesPreparer prepares the GetPageRanges request.
func (client Client) GetPageRangesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "pagelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPageRangesSender sends the GetPageRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPageRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPageRangesResponder handles the response to the GetPageRanges request. The method always
// closes the http.Response Body.
func (client Client) GetPageRangesResponder(resp *http.Response) (result GetPageRangesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/incremental_copy_blob.go 0000664 0000000 0000000 00000010703 14232154237 0025005 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type IncrementalCopyBlobInput struct {
CopySource string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
}
// IncrementalCopyBlob 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.
func (client Client) IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`input.CopySource` cannot be an empty string.")
}
req, err := client.IncrementalCopyBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", nil, "Failure preparing request")
return
}
resp, err := client.IncrementalCopyBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure sending request")
return
}
result, err = client.IncrementalCopyBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure responding to request")
return
}
return
}
// IncrementalCopyBlobPreparer prepares the IncrementalCopyBlob request.
func (client Client) IncrementalCopyBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "incrementalcopy"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// IncrementalCopyBlobSender sends the IncrementalCopyBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) IncrementalCopyBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// IncrementalCopyBlobResponder handles the response to the IncrementalCopyBlob request. The method always
// closes the http.Response Body.
func (client Client) IncrementalCopyBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/lease_acquire.go 0000664 0000000 0000000 00000011503 14232154237 0023255 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput struct {
// The ID of the existing Lease, if leased
LeaseID *string
// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires.
// A non-infinite lease can be between 15 and 60 seconds
LeaseDuration int
// The Proposed new ID for the Lease
ProposedLeaseID *string
}
type AcquireLeaseResult struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a blob for write and delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseID` cannot be an empty string, if specified.")
}
if input.ProposedLeaseID != nil && *input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.ProposedLeaseID` cannot be an empty string, if specified.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.ProposedLeaseID != nil {
headers["x-ms-proposed-lease-id"] = *input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResult, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/lease_break.go 0000664 0000000 0000000 00000010614 14232154237 0022712 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks an existing lock on a blob using the LeaseID.
func (client Client) BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/lease_change.go 0000664 0000000 0000000 00000007777 14232154237 0023073 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes an existing lock on a blob for another lock.
func (client Client) ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`blobName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/lease_release.go 0000664 0000000 0000000 00000006720 14232154237 0023251 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases a lock based on the Lease ID.
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/lease_renew.go 0000664 0000000 0000000 00000006555 14232154237 0022757 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
func (client Client) RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/lease_test.go 0000664 0000000 0000000 00000007152 14232154237 0022610 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLeaseLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
defer blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{})
// Test begins here
t.Logf("[DEBUG] Acquiring Lease..")
leaseInput := AcquireLeaseInput{
LeaseDuration: -1,
}
leaseInfo, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Changing Lease..")
changeLeaseInput := ChangeLeaseInput{
ExistingLeaseID: leaseInfo.LeaseID,
ProposedLeaseID: "31f5bb01-cdd9-4166-bcdc-95186076bde0",
}
changeLeaseResult, err := blobClient.ChangeLease(ctx, accountName, containerName, fileName, changeLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
t.Logf("[DEBUG] New Lease ID: %q", changeLeaseResult.LeaseID)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, changeLeaseResult.LeaseID); err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Acquiring a new lease..")
leaseInput = AcquireLeaseInput{
LeaseDuration: 30,
}
leaseInfo, err = blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Renewing lease..")
if _, err := blobClient.RenewLease(ctx, accountName, containerName, fileName, leaseInfo.LeaseID); err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
t.Logf("[DEBUG] Breaking lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseInfo.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/lifecycle_test.go 0000664 0000000 0000000 00000012612 14232154237 0023453 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageBlob = Client{}
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Blob Properties..")
details, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 0 {
t.Fatalf("Expected there to be no items of metadata but got %d", len(details.MetaData))
}
t.Logf("[DEBUG] Checking it's returned in the List API..")
listInput := containers.ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 1 {
t.Fatalf("Expected there to be 1 blob in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Setting MetaData..")
metaDataInput := SetMetaDataInput{
MetaData: map[string]string{
"hello": "there",
},
}
if _, err := blobClient.SetMetaData(ctx, accountName, containerName, fileName, metaDataInput); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 1 {
t.Fatalf("Expected there to be 1 item of metadata but got %d", len(details.MetaData))
}
if details.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", details.MetaData["there"])
}
t.Logf("[DEBUG] Retrieving the Block List..")
getBlockListInput := GetBlockListInput{
BlockListType: All,
}
blockList, err := blobClient.GetBlockList(ctx, accountName, containerName, fileName, getBlockListInput)
if err != nil {
t.Fatalf("Error retrieving Block List: %s", err)
}
// since this is a copy from an existing file, all blocks should be present
if len(blockList.CommittedBlocks.Blocks) == 0 {
t.Fatalf("Expected there to be committed blocks but there weren't!")
}
if len(blockList.UncommittedBlocks.Blocks) != 0 {
t.Fatalf("Expected all blocks to be committed but got %d uncommitted blocks", len(blockList.UncommittedBlocks.Blocks))
}
t.Logf("[DEBUG] Changing the Access Tiers..")
tiers := []AccessTier{
Hot,
Cool,
Archive,
}
for _, tier := range tiers {
t.Logf("[DEBUG] Updating the Access Tier to %q..", string(tier))
if _, err := blobClient.SetTier(ctx, accountName, containerName, fileName, tier); err != nil {
t.Fatalf("Error setting the Access Tier: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
if details.AccessTier != tier {
t.Fatalf("Expected the AccessTier to be %q but got %q", tier, details.AccessTier)
}
}
t.Logf("[DEBUG] Deleting Blob")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/metadata_set.go 0000664 0000000 0000000 00000007724 14232154237 0023120 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SetMetaDataInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// Any metadata which should be added to this blob
MetaData map[string]string
}
// SetMetaData marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "GetProperties", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/models.go 0000664 0000000 0000000 00000002714 14232154237 0021742 0 ustar 00root root 0000000 0000000 package blobs
type AccessTier string
var (
Archive AccessTier = "Archive"
Cool AccessTier = "Cool"
Hot AccessTier = "Hot"
)
type ArchiveStatus string
var (
None ArchiveStatus = ""
RehydratePendingToCool ArchiveStatus = "rehydrate-pending-to-cool"
RehydratePendingToHot ArchiveStatus = "rehydrate-pending-to-hot"
)
type BlockListType string
var (
All BlockListType = "all"
Committed BlockListType = "committed"
Uncommitted BlockListType = "uncommitted"
)
type Block struct {
// The base64-encoded Block ID
Name string `xml:"Name"`
// The size of the Block in Bytes
Size int64 `xml:"Size"`
}
type BlobType string
var (
AppendBlob BlobType = "AppendBlob"
BlockBlob BlobType = "BlockBlob"
PageBlob BlobType = "PageBlob"
)
type CommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
type CopyStatus string
var (
Aborted CopyStatus = "aborted"
Failed CopyStatus = "failed"
Pending CopyStatus = "pending"
Success CopyStatus = "success"
)
type LeaseDuration string
var (
Fixed LeaseDuration = "fixed"
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
type UncommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/properties_get.go 0000664 0000000 0000000 00000031314 14232154237 0023510 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
type GetPropertiesResult struct {
autorest.Response
// The tier of page blob on a premium storage account or tier of block blob on blob storage or general purpose v2 account.
AccessTier AccessTier
// This gives the last time tier was changed on the object.
// This header is returned only if tier on block blob was ever set.
// The date format follows RFC 1123
AccessTierChangeTime string
// For page blobs on a premium storage account only.
// If the access tier is not explicitly set on the blob, the tier is inferred based on its content length
// and this header will be returned with true value.
// For block blobs on Blob Storage or general purpose v2 account, if the blob does not have the access tier
// set then we infer the tier from the storage account properties. This header is set only if the block blob
// tier is inferred
AccessTierInferred bool
// For blob storage or general purpose v2 account.
// If the blob is being rehydrated and is not complete then this header is returned indicating
// that rehydrate is pending and also tells the destination tier
ArchiveStatus ArchiveStatus
// The number of committed blocks present in the blob.
// This header is returned only for append blobs.
BlobCommittedBlockCount string
// The current sequence number for a page blob.
// This header is not returned for block blobs or append blobs.
// This header is not returned for block blobs.
BlobSequenceNumber string
// The blob type.
BlobType BlobType
// If the Cache-Control request header has previously been set for the blob, that value is returned in this header.
CacheControl string
// The Content-Disposition response header field conveys additional information about how to process
// the response payload, and also can be used to attach additional metadata.
// For example, if set to attachment, it indicates that the user-agent should not display the response,
// but instead show a Save As dialog.
ContentDisposition string
// If the Content-Encoding request header has previously been set for the blob,
// that value is returned in this header.
ContentEncoding string
// If the Content-Language request header has previously been set for the blob,
// that value is returned in this header.
ContentLanguage string
// The size of the blob in bytes.
// For a page blob, this header returns the value of the x-ms-blob-content-length header stored with the blob.
ContentLength int64
// The content type specified for the blob.
// If no content type was specified, the default content type is `application/octet-stream`.
ContentType string
// If the Content-MD5 header has been set for the blob, this response header is returned so that
// the client can check for message content integrity.
ContentMD5 string
// Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob.
// This value can specify the time of a completed, aborted, or failed copy attempt.
// This header does not appear if a copy is pending, if this blob has never been the
// destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob
// operation using Set Blob Properties, Put Blob, or Put Block List.
CopyCompletionTime string
// Included if the blob is incremental copy blob or incremental copy snapshot, if x-ms-copy-status is success.
// Snapshot time of the last successful incremental copy snapshot for this blob
CopyDestinationSnapshot string
// String identifier for the last attempted Copy Blob operation where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyID string
// Contains the number of bytes copied and the total bytes in the source in the last attempted
// Copy Blob operation where this blob was the destination blob.
// Can show between 0 and Content-Length bytes copied.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyProgress string
// URL up to 2 KB in length that specifies the source blob used in the last attempted Copy Blob operation
// where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List
CopySource string
// State of the copy operation identified by x-ms-copy-id, with these values:
// - success: Copy completed successfully.
// - pending: Copy is in progress.
// Check x-ms-copy-status-description if intermittent, non-fatal errors
// impede copy progress but don’t cause failure.
// - aborted: Copy was ended by Abort Copy Blob.
// - failed: Copy failed. See x-ms- copy-status-description for failure details.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a completed Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatus CopyStatus
// Describes cause of fatal or non-fatal copy operation failure.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatusDescription string
// The date/time at which the blob was created. The date format follows RFC 1123
CreationTime string
// The ETag contains a value that you can use to perform operations conditionally
ETag string
// Included if the blob is incremental copy blob.
IncrementalCopy bool
// The date/time that the blob was last modified. The date format follows RFC 1123.
LastModified string
// When a blob is leased, specifies whether the lease is of infinite or fixed duration
LeaseDuration LeaseDuration
// The lease state of the blob
LeaseState LeaseState
LeaseStatus LeaseStatus
// A set of name-value pairs that correspond to the user-defined metadata associated with this blob
MetaData map[string]string
// Is the Storage Account encrypted using server-side encryption? This should always return true
ServerEncrypted bool
}
// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the blob
func (client Client) GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.AccessTier = AccessTier(resp.Header.Get("x-ms-access-tier"))
result.AccessTierChangeTime = resp.Header.Get(" x-ms-access-tier-change-time")
result.ArchiveStatus = ArchiveStatus(resp.Header.Get(" x-ms-archive-status"))
result.BlobCommittedBlockCount = resp.Header.Get("x-ms-blob-committed-block-count")
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.BlobType = BlobType(resp.Header.Get("x-ms-blob-type"))
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.CopyDestinationSnapshot = resp.Header.Get("x-ms-copy-destination-snapshot")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = CopyStatus(resp.Header.Get("x-ms-copy-status"))
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CreationTime = resp.Header.Get("x-ms-creation-time")
result.ETag = resp.Header.Get("Etag")
result.LastModified = resp.Header.Get("Last-Modified")
result.LeaseDuration = LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.MetaData = metadata.ParseFromHeaders(resp.Header)
if v := resp.Header.Get("x-ms-access-tier-inferred"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.AccessTierInferred = b
}
if v := resp.Header.Get("Content-Length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
}
result.ContentLength = int64(i)
}
if v := resp.Header.Get("x-ms-incremental-copy"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
if v := resp.Header.Get("x-ms-server-encrypted"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/properties_set.go 0000664 0000000 0000000 00000012111 14232154237 0023516 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
CacheControl *string
ContentType *string
ContentMD5 *string
ContentEncoding *string
ContentLanguage *string
LeaseID *string
ContentDisposition *string
ContentLength *int64
SequenceNumberAction *SequenceNumberAction
BlobSequenceNumber *string
}
type SetPropertiesResult struct {
autorest.Response
BlobSequenceNumber string
Etag string
}
// SetProperties sets system properties on the blob.
func (client Client) SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
type SequenceNumberAction string
var (
Increment SequenceNumberAction = "increment"
Max SequenceNumberAction = "max"
Update SequenceNumberAction = "update"
)
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.ContentLength != nil {
headers["x-ms-blob-content-length"] = *input.ContentLength
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SequenceNumberAction != nil {
headers["x-ms-sequence-number-action"] = string(*input.SequenceNumberAction)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result SetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.Etag = resp.Header.Get("Etag")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_append_blob.go 0000664 0000000 0000000 00000011323 14232154237 0023610 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutAppendBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutAppendBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new append blob, or updates the content of an existing blob.
func (client Client) PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutAppendBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutAppendBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutAppendBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure sending request")
return
}
result, err = client.PutAppendBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure responding to request")
return
}
return
}
// PutAppendBlobPreparer prepares the PutAppendBlob request.
func (client Client) PutAppendBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(AppendBlob),
"x-ms-version": APIVersion,
// For a page blob or an append blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutAppendBlobSender sends the PutAppendBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutAppendBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutAppendBlobResponder handles the response to the PutAppendBlob request. The method always
// closes the http.Response Body.
func (client Client) PutAppendBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_block.go 0000664 0000000 0000000 00000010100 14232154237 0022425 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockInput struct {
BlockID string
Content []byte
ContentMD5 *string
LeaseID *string
}
type PutBlockResult struct {
autorest.Response
ContentMD5 string
}
// PutBlock creates a new block to be committed as part of a blob.
func (client Client) PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.BlockID` cannot be an empty string.")
}
if len(input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.Content` cannot be empty.")
}
req, err := client.PutBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure sending request")
return
}
result, err = client.PutBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure responding to request")
return
}
return
}
// PutBlockPreparer prepares the PutBlock request.
func (client Client) PutBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Content-Length": int(len(input.Content)),
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockSender sends the PutBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockResponder handles the response to the PutBlock request. The method always
// closes the http.Response Body.
func (client Client) PutBlockResponder(resp *http.Response) (result PutBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_block_blob.go 0000664 0000000 0000000 00000011750 14232154237 0023437 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutBlockBlobInput struct {
CacheControl *string
Content *[]byte
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutBlockBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block append blob, or updates the content of an existing block blob.
func (client Client) PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`input.Content` must either be nil or not empty.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutBlockBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutBlockBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure sending request")
return
}
result, err = client.PutBlockBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure responding to request")
return
}
return
}
// PutBlockBlobPreparer prepares the PutBlockBlob request.
func (client Client) PutBlockBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(BlockBlob),
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockBlobSender sends the PutBlockBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockBlobResponder handles the response to the PutBlockBlob request. The method always
// closes the http.Response Body.
func (client Client) PutBlockBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_block_blob_file.go 0000664 0000000 0000000 00000001510 14232154237 0024427 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"io"
"os"
)
// PutBlockBlobFromFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
bytes := make([]byte, fileSize)
_, err = file.ReadAt(bytes, 0)
if err != nil {
if err != io.EOF {
return fmt.Errorf("Error reading bytes: %s", err)
}
}
input.Content = &bytes
if _, err = client.PutBlockBlob(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error putting bytes: %s", err)
}
return nil
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_block_list.go 0000664 0000000 0000000 00000012220 14232154237 0023465 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type BlockList struct {
CommittedBlockIDs []BlockID `xml:"Committed,omitempty"`
UncommittedBlockIDs []BlockID `xml:"Uncommitted,omitempty"`
LatestBlockIDs []BlockID `xml:"Latest,omitempty"`
}
type BlockID struct {
Value string `xml:",chardata"`
}
type PutBlockListInput struct {
BlockList BlockList
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
MetaData map[string]string
LeaseID *string
}
type PutBlockListResult struct {
autorest.Response
ContentMD5 string
ETag string
LastModified string
}
// PutBlockList 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.
func (client Client) PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.PutBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure sending request")
return
}
result, err = client.PutBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure responding to request")
return
}
return
}
// PutBlockListPreparer prepares the PutBlockList request.
func (client Client) PutBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(input.BlockList))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockListSender sends the PutBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockListResponder handles the response to the PutBlockList request. The method always
// closes the http.Response Body.
func (client Client) PutBlockListResponder(resp *http.Response) (result PutBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_block_url.go 0000664 0000000 0000000 00000010564 14232154237 0023325 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockFromURLInput struct {
BlockID string
CopySource string
ContentMD5 *string
LeaseID *string
Range *string
}
type PutBlockFromURLResult struct {
autorest.Response
ContentMD5 string
}
// PutBlockFromURL creates a new block to be committed as part of a blob where the contents are read from a URL
func (client Client) PutBlockFromURL(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (result PutBlockFromURLResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.BlockID` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.CopySource` cannot be an empty string.")
}
req, err := client.PutBlockFromURLPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockFromURLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure sending request")
return
}
result, err = client.PutBlockFromURLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure responding to request")
return
}
return
}
// PutBlockFromURLPreparer prepares the PutBlockFromURL request.
func (client Client) PutBlockFromURLPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.ContentMD5 != nil {
headers["x-ms-source-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Range != nil {
headers["x-ms-source-range"] = *input.Range
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockFromURLSender sends the PutBlockFromURL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockFromURLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockFromURLResponder handles the response to the PutBlockFromURL request. The method always
// closes the http.Response Body.
func (client Client) PutBlockFromURLResponder(resp *http.Response) (result PutBlockFromURLResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_page_blob.go 0000664 0000000 0000000 00000012264 14232154237 0023262 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutPageBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
BlobContentLengthBytes int64
BlobSequenceNumber *int64
AccessTier *AccessTier
}
// PutPageBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block blob, or updates the content of an existing page blob.
func (client Client) PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`blobName` cannot be an empty string.")
}
if input.BlobContentLengthBytes == 0 || input.BlobContentLengthBytes%512 != 0 {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`input.BlobContentLengthBytes` must be aligned to a 512-byte boundary.")
}
req, err := client.PutPageBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutPageBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure sending request")
return
}
result, err = client.PutPageBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure responding to request")
return
}
return
}
// PutPageBlobPreparer prepares the PutPageBlob request.
func (client Client) PutPageBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(PageBlob),
"x-ms-version": APIVersion,
// For a page blob or an page blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
// This header specifies the maximum size for the page blob, up to 8 TB.
// The page blob size must be aligned to a 512-byte boundary.
"x-ms-blob-content-length": input.BlobContentLengthBytes,
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageBlobSender sends the PutPageBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageBlobResponder handles the response to the PutPageBlob request. The method always
// closes the http.Response Body.
func (client Client) PutPageBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_page_clear.go 0000664 0000000 0000000 00000007556 14232154237 0023442 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageClearInput struct {
StartByte int64
EndByte int64
LeaseID *string
}
// PutPageClear clears a range of pages within a page blob.
func (client Client) PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.EndByte` must be greater than 0.")
}
req, err := client.PutPageClearPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", nil, "Failure preparing request")
return
}
resp, err := client.PutPageClearSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure sending request")
return
}
result, err = client.PutPageClearResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure responding to request")
return
}
return
}
// PutPageClearPreparer prepares the PutPageClear request.
func (client Client) PutPageClearPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageClearSender sends the PutPageClear request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageClearSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageClearResponder handles the response to the PutPageClear request. The method always
// closes the http.Response Body.
func (client Client) PutPageClearResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/put_page_update.go 0000664 0000000 0000000 00000012777 14232154237 0023637 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageUpdateInput struct {
StartByte int64
EndByte int64
Content []byte
IfSequenceNumberEQ *string
IfSequenceNumberLE *string
IfSequenceNumberLT *string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
LeaseID *string
}
type PutPageUpdateResult struct {
autorest.Response
BlobSequenceNumber string
ContentMD5 string
LastModified string
}
// PutPageUpdate writes a range of pages to a page blob.
func (client Client) PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.EndByte` must be greater than 0.")
}
expectedSize := (input.EndByte - input.StartByte) + 1
actualSize := int64(len(input.Content))
if expectedSize != actualSize {
return result, validation.NewError("blobs.Client", "PutPageUpdate", fmt.Sprintf("Content Size was defined as %d but got %d.", expectedSize, actualSize))
}
req, err := client.PutPageUpdatePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", nil, "Failure preparing request")
return
}
resp, err := client.PutPageUpdateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure sending request")
return
}
result, err = client.PutPageUpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure responding to request")
return
}
return
}
// PutPageUpdatePreparer prepares the PutPageUpdate request.
func (client Client) PutPageUpdatePreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
"Content-Length": int(len(input.Content)),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfSequenceNumberEQ != nil {
headers["x-ms-if-sequence-number-eq"] = *input.IfSequenceNumberEQ
}
if input.IfSequenceNumberLE != nil {
headers["x-ms-if-sequence-number-le"] = *input.IfSequenceNumberLE
}
if input.IfSequenceNumberLT != nil {
headers["x-ms-if-sequence-number-lt"] = *input.IfSequenceNumberLT
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageUpdateSender sends the PutPageUpdate request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageUpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageUpdateResponder handles the response to the PutPageUpdate request. The method always
// closes the http.Response Body.
func (client Client) PutPageUpdateResponder(resp *http.Response) (result PutPageUpdateResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/resource_id.go 0000664 0000000 0000000 00000003060 14232154237 0022755 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Blob
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName, blobName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, containerName, blobName)
}
type ResourceID struct {
AccountName string
ContainerName string
BlobName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Blob Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar/example.vhd
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
containerName := segments[0]
blobName := strings.TrimPrefix(path, containerName)
blobName = strings.TrimPrefix(blobName, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
BlobName: blobName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/resource_id_test.go 0000664 0000000 0000000 00000006670 14232154237 0024026 0 ustar 00root root 0000000 0000000 package blobs
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1", "blob1.vhd")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "blob1.vhd" {
t.Fatalf("Expected Blob Name to be `blob1.vhd` but got %q", actual.BlobName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/example/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/example/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/example/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/example/blob1.vhd",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "example/blob1.vhd" {
t.Fatalf("Expected Blob Name to be `example/blob1.vhd` but got %q", actual.BlobName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/set_tier.go 0000664 0000000 0000000 00000006325 14232154237 0022277 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetTier sets the tier on a blob.
func (client Client) SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`blobName` cannot be an empty string.")
}
req, err := client.SetTierPreparer(ctx, accountName, containerName, blobName, tier)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", nil, "Failure preparing request")
return
}
resp, err := client.SetTierSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure sending request")
return
}
result, err = client.SetTierResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure responding to request")
return
}
return
}
// SetTierPreparer prepares the SetTier request.
func (client Client) SetTierPreparer(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "tier"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-access-tier": string(tier),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetTierSender sends the SetTier request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetTierSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetTierResponder handles the response to the SetTier request. The method always
// closes the http.Response Body.
func (client Client) SetTierResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/snapshot.go 0000664 0000000 0000000 00000013463 14232154237 0022321 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// MetaData is a user-defined name-value pair associated with the blob.
// If no name-value pairs are specified, the operation will copy the base blob metadata to the snapshot.
// If one or more name-value pairs are specified, the snapshot is created with the specified metadata,
// and metadata is not copied from the base blob.
MetaData map[string]string
// A DateTime value which will only snapshot the blob if it has been modified since the specified date/time
// If the base blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value which will only snapshot the blob if it has not been modified since the specified date/time
// If the base blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value to snapshot the blob only if its ETag value matches the value specified.
// If the values do not match, the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value for this conditional header to snapshot the blob only if its ETag value
// does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
}
type SnapshotResult struct {
autorest.Response
// The ETag of the snapshot
ETag string
// A DateTime value that uniquely identifies the snapshot.
// The value of this header indicates the snapshot version,
// and may be used in subsequent requests to access the snapshot.
SnapshotDateTime string
}
// Snapshot captures a Snapshot of a given Blob
func (client Client) Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "Snapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", nil, "Failure preparing request")
return
}
resp, err := client.SnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure sending request")
return
}
result, err = client.SnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure responding to request")
return
}
return
}
// SnapshotPreparer prepares the Snapshot request.
func (client Client) SnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SnapshotSender sends the Snapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SnapshotResponder handles the response to the Snapshot request. The method always
// closes the http.Response Body.
func (client Client) SnapshotResponder(resp *http.Response) (result SnapshotResult, err error) {
if resp != nil && resp.Header != nil {
result.ETag = resp.Header.Get("ETag")
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/snapshot_get_properties.go 0000664 0000000 0000000 00000006445 14232154237 0025436 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetSnapshotPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The ID of the Snapshot which should be retrieved
SnapshotID string
}
// GetSnapshotProperties returns all user-defined metadata, standard HTTP properties, and system properties for
// the specified snapshot of a blob
func (client Client) GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`blobName` cannot be an empty string.")
}
if input.SnapshotID == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`input.SnapshotID` cannot be an empty string.")
}
req, err := client.GetSnapshotPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", nil, "Failure preparing request")
return
}
// we re-use the GetProperties methods since this is otherwise the same
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/snapshot_test.go 0000664 0000000 0000000 00000013411 14232154237 0023351 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestSnapshotLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatalf("Error creating: %s", err)
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] First Snapshot..")
firstSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{})
if err != nil {
t.Fatalf("Error taking first snapshot: %s", err)
}
t.Logf("[DEBUG] First Snapshot ID: %q", firstSnapshot.SnapshotDateTime)
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
t.Logf("[DEBUG] Second Snapshot..")
secondSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
MetaData: map[string]string{
"hello": "world",
},
})
if err != nil {
t.Fatalf("Error taking Second snapshot: %s", err)
}
t.Logf("[DEBUG] Second Snapshot ID: %q", secondSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Leasing the Blob..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
// infinite
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error leasing Blob: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Third Snapshot..")
thirdSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error taking Third snapshot: %s", err)
}
t.Logf("[DEBUG] Third Snapshot ID: %q", thirdSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, leaseDetails.LeaseID); err != nil {
t.Fatalf("Error releasing Lease: %s", err)
}
// get the properties from the blob, which should include the LastModifiedDate
t.Logf("[DEBUG] Retrieving Properties for Blob")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
// confirm that the If-Modified-None returns an error
t.Logf("[DEBUG] Third Snapshot..")
fourthSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
IfModifiedSince: &props.LastModified,
})
if err == nil {
t.Fatalf("Expected an error but didn't get one")
}
if fourthSnapshot.Response.StatusCode != http.StatusPreconditionFailed {
t.Fatalf("Expected the status code to be Precondition Failed but got: %d", fourthSnapshot.Response.StatusCode)
}
t.Logf("[DEBUG] Retrieving the Second Snapshot Properties..")
getSecondSnapshotInput := GetSnapshotPropertiesInput{
SnapshotID: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput); err != nil {
t.Fatalf("Error retrieving properties for the second snapshot: %s", err)
}
t.Logf("[DEBUG] Deleting the Second Snapshot..")
deleteSnapshotInput := DeleteSnapshotInput{
SnapshotDateTime: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.DeleteSnapshot(ctx, accountName, containerName, fileName, deleteSnapshotInput); err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Second Snapshot Properties..")
secondSnapshotProps, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput)
if err == nil {
t.Fatalf("Expected an error retrieving the snapshot but got none")
}
if secondSnapshotProps.Response.StatusCode != http.StatusNotFound {
t.Fatalf("Expected the status code to be %d but got %q", http.StatusNoContent, secondSnapshotProps.Response.StatusCode)
}
t.Logf("[DEBUG] Deleting all the snapshots..")
if _, err := blobClient.DeleteSnapshots(ctx, accountName, containerName, fileName, DeleteSnapshotsInput{}); err != nil {
t.Fatalf("Error deleting snapshots: %s", err)
}
t.Logf("[DEBUG] Deleting the Blob..")
deleteInput := DeleteInput{
DeleteSnapshots: false,
}
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, deleteInput); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/undelete.go 0000664 0000000 0000000 00000006323 14232154237 0022264 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Undelete restores the contents and metadata of soft deleted blob and any associated soft deleted snapshots.
func (client Client) Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`blobName` cannot be an empty string.")
}
req, err := client.UndeletePreparer(ctx, accountName, containerName, blobName)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", nil, "Failure preparing request")
return
}
resp, err := client.UndeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure sending request")
return
}
result, err = client.UndeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure responding to request")
return
}
return
}
// UndeletePreparer prepares the Undelete request.
func (client Client) UndeletePreparer(ctx context.Context, accountName, containerName, blobName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "undelete"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UndeleteSender sends the Undelete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UndeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UndeleteResponder handles the response to the Undelete request. The method always
// closes the http.Response Body.
func (client Client) UndeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/blobs/version.go 0000664 0000000 0000000 00000000463 14232154237 0022143 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/ 0000775 0000000 0000000 00000000000 14232154237 0021170 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/blob/containers/README.md 0000664 0000000 0000000 00000002257 14232154237 0022455 0 ustar 00root root 0000000 0000000 ## Blob Storage Container SDK for API version 2019-12-12
This package allows you to interact with the Containers Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
Note: when using the `ListBlobs` operation, only `SharedKeyLite` authentication is supported.
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/containers"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
containersClient := containers.New()
containersClient.Client.Authorizer = storageAuth
ctx := context.TODO()
createInput := containers.CreateInput{
AccessLevel: containers.Private,
}
if _, err := containersClient.Create(ctx, accountName, containerName, createInput); err != nil {
return fmt.Errorf("Error creating Container: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/blob/containers/api.go 0000664 0000000 0000000 00000003675 14232154237 0022303 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageContainer interface {
Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error)
Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error)
GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error)
GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error)
AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error)
BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error)
ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error)
ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error)
RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error)
ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error)
GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, containerName string) string
SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error)
SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error)
SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error)
SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/client.go 0000664 0000000 0000000 00000001632 14232154237 0022777 0 ustar 00root root 0000000 0000000 package containers
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Containers.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
func (client Client) setAccessLevelIntoHeaders(headers map[string]interface{}, level AccessLevel) map[string]interface{} {
// If this header is not included in the request, container data is private to the account owner.
if level != Private {
headers["x-ms-blob-public-access"] = string(level)
}
return headers
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/create.go 0000664 0000000 0000000 00000010233 14232154237 0022761 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies whether data in the container may be accessed publicly and the level of access
AccessLevel AccessLevel
// A name-value pair to associate with the container as metadata.
MetaData map[string]string
}
type CreateResponse struct {
autorest.Response
Error *ErrorResponse `xml:"Error"`
}
// Create creates a new container under the specified account.
// If the container with the same name already exists, the operation fails.
func (client Client) Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Create", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Create", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("containers.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, containerName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, input.AccessLevel)
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result CreateResponse, err error) {
successfulStatusCodes := []int{
http.StatusCreated,
}
if autorest.ResponseHasStatusCode(resp, successfulStatusCodes...) {
// when successful there's no response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
} else {
// however when there's an error the error's in the response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/delete.go 0000664 0000000 0000000 00000005600 14232154237 0022762 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete marks the specified container for deletion.
// The container and any blobs contained within it are later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Delete", "`containerName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, containerName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/get_properties.go 0000664 0000000 0000000 00000011677 14232154237 0024566 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// GetProperties returns the properties for this Container without a Lease
func (client Client) GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error) {
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
return client.GetPropertiesWithLeaseID(ctx, accountName, containerName, "")
}
// GetPropertiesWithLeaseID returns the properties for this Container using the specified LeaseID
func (client Client) GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`containerName` cannot be an empty string.")
}
req, err := client.GetPropertiesWithLeaseIDPreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesWithLeaseIDSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesWithLeaseIDPreparer prepares the GetPropertiesWithLeaseID request.
func (client Client) GetPropertiesWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesWithLeaseIDSender sends the GetPropertiesWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesWithLeaseIDResponder handles the response to the GetPropertiesWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesWithLeaseIDResponder(resp *http.Response) (result ContainerProperties, err error) {
if resp != nil {
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
if result.LeaseStatus == Locked {
duration := LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseDuration = &duration
}
// If this header is not returned in the response, the container is private to the account owner.
accessLevel := resp.Header.Get("x-ms-blob-public-access")
if accessLevel != "" {
result.AccessLevel = AccessLevel(accessLevel)
} else {
result.AccessLevel = Private
}
// we can't necessarily use strconv.ParseBool here since this could be nil (only in some API versions)
result.HasImmutabilityPolicy = strings.EqualFold(resp.Header.Get("x-ms-has-immutability-policy"), "true")
result.HasLegalHold = strings.EqualFold(resp.Header.Get("x-ms-has-legal-hold"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/lease_acquire.go 0000664 0000000 0000000 00000007762 14232154237 0024335 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput 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
LeaseDuration int
ProposedLeaseID string
}
type AcquireLeaseResponse struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a container for delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("containers.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName string, containerName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.ProposedLeaseID != "" {
headers["x-ms-proposed-lease-id"] = input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/lease_break.go 0000664 0000000 0000000 00000010521 14232154237 0023753 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strconv"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks a lock based on it's Lease ID
func (client Client) BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName string, containerName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result BreakLeaseResponse, err error) {
if resp != nil {
leaseRaw := resp.Header.Get("x-ms-lease-time")
if leaseRaw != "" {
i, err := strconv.Atoi(leaseRaw)
if err == nil {
result.LeaseTime = i
}
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/lease_change.go 0000664 0000000 0000000 00000007356 14232154237 0024130 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes the lock from one Lease ID to another Lease ID
func (client Client) ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName string, containerName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/lease_release.go 0000664 0000000 0000000 00000006324 14232154237 0024315 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases the lock based on the Lease ID
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/lease_renew.go 0000664 0000000 0000000 00000006250 14232154237 0024013 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// RenewLease renews the lock based on the Lease ID
func (client Client) RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/lifecycle_test.go 0000664 0000000 0000000 00000013122 14232154237 0024514 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageContainer = Client{}
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
// first let's test an empty container
input := CreateInput{}
_, err = containersClient.Create(ctx, accountName, containerName, input)
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
container, err := containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error retrieving: %s", err))
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if len(container.MetaData) != 0 {
t.Fatalf("Expected MetaData to be empty but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the metadata
metaData := map[string]string{
"dont": "kill-my-vibe",
}
_, err = containersClient.SetMetaData(ctx, accountName, containerName, metaData)
if err != nil {
t.Fatal(fmt.Errorf("Error updating metadata: %s", err))
}
// give azure time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.MetaData["dont"] != "kill-my-vibe" {
t.Fatalf("Expected `kill-my-vibe` but got %q", container.MetaData["dont"])
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the ACL
_, err = containersClient.SetAccessControl(ctx, accountName, containerName, Blob)
if err != nil {
t.Fatal(fmt.Errorf("Error updating ACL's: %s", err))
}
// give azure some time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if container.AccessLevel != Blob {
t.Fatalf("Expected Access Level to be Blob but got %q", container.AccessLevel)
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// acquire a lease for 30s
acquireLeaseInput := AcquireLeaseInput{
LeaseDuration: 30,
}
acquireLeaseResp, err := containersClient.AcquireLease(ctx, accountName, containerName, acquireLeaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %s", acquireLeaseResp.LeaseID)
// we should then be able to update the ID
t.Logf("[DEBUG] Changing lease..")
updateLeaseInput := ChangeLeaseInput{
ExistingLeaseID: acquireLeaseResp.LeaseID,
ProposedLeaseID: "aaaabbbb-aaaa-bbbb-cccc-aaaabbbbcccc",
}
updateLeaseResp, err := containersClient.ChangeLease(ctx, accountName, containerName, updateLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
// then renew it
_, err = containersClient.RenewLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
// and then give it a timeout
breakPeriod := 20
breakLeaseInput := BreakLeaseInput{
LeaseID: updateLeaseResp.LeaseID,
BreakPeriod: &breakPeriod,
}
breakLeaseResp, err := containersClient.BreakLease(ctx, accountName, containerName, breakLeaseInput)
if err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
if breakLeaseResp.LeaseTime == 0 {
t.Fatalf("Lease broke immediately when should have waited: %d", breakLeaseResp.LeaseTime)
}
// and finally ditch it
_, err = containersClient.ReleaseLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Listing blobs in the container..")
listInput := ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 0 {
t.Fatalf("Expected there to be no blobs in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Deleting..")
_, err = containersClient.Delete(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/list_blobs.go 0000664 0000000 0000000 00000015033 14232154237 0023655 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListBlobsInput struct {
Delimiter *string
Include *[]Dataset
Marker *string
MaxResults *int
Prefix *string
}
type ListBlobsResult struct {
autorest.Response
Delimiter string `xml:"Delimiter"`
Marker string `xml:"Marker"`
MaxResults int `xml:"MaxResults"`
NextMarker *string `xml:"NextMarker,omitempty"`
Prefix string `xml:"Prefix"`
Blobs Blobs `xml:"Blobs"`
}
type Blobs struct {
Blobs []BlobDetails `xml:"Blob"`
BlobPrefix *BlobPrefix `xml:"BlobPrefix"`
}
type BlobDetails struct {
Name string `xml:"Name"`
Deleted bool `xml:"Deleted,omitempty"`
MetaData map[string]interface{} `map:"Metadata,omitempty"`
Properties *BlobProperties `xml:"Properties,omitempty"`
Snapshot *string `xml:"Snapshot,omitempty"`
}
type BlobProperties struct {
AccessTier *string `xml:"AccessTier,omitempty"`
AccessTierInferred *bool `xml:"AccessTierInferred,omitempty"`
AccessTierChangeTime *string `xml:"AccessTierChangeTime,omitempty"`
BlobType *string `xml:"BlobType,omitempty"`
BlobSequenceNumber *string `xml:"x-ms-blob-sequence-number,omitempty"`
CacheControl *string `xml:"Cache-Control,omitempty"`
ContentEncoding *string `xml:"ContentEncoding,omitempty"`
ContentLanguage *string `xml:"Content-Language,omitempty"`
ContentLength *int64 `xml:"Content-Length,omitempty"`
ContentMD5 *string `xml:"Content-MD5,omitempty"`
ContentType *string `xml:"Content-Type,omitempty"`
CopyCompletionTime *string `xml:"CopyCompletionTime,omitempty"`
CopyId *string `xml:"CopyId,omitempty"`
CopyStatus *string `xml:"CopyStatus,omitempty"`
CopySource *string `xml:"CopySource,omitempty"`
CopyProgress *string `xml:"CopyProgress,omitempty"`
CopyStatusDescription *string `xml:"CopyStatusDescription,omitempty"`
CreationTime *string `xml:"CreationTime,omitempty"`
ETag *string `xml:"Etag,omitempty"`
DeletedTime *string `xml:"DeletedTime,omitempty"`
IncrementalCopy *bool `xml:"IncrementalCopy,omitempty"`
LastModified *string `xml:"Last-Modified,omitempty"`
LeaseDuration *string `xml:"LeaseDuration,omitempty"`
LeaseState *string `xml:"LeaseState,omitempty"`
LeaseStatus *string `xml:"LeaseStatus,omitempty"`
RemainingRetentionDays *string `xml:"RemainingRetentionDays,omitempty"`
ServerEncrypted *bool `xml:"ServerEncrypted,omitempty"`
}
type BlobPrefix struct {
Name string `xml:"Name"`
}
// ListBlobs lists the blobs matching the specified query within the specified Container
func (client Client) ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`containerName` cannot be an empty string.")
}
if input.MaxResults != nil && (*input.MaxResults <= 0 || *input.MaxResults > 5000) {
return result, validation.NewError("containers.Client", "ListBlobs", "`input.MaxResults` can either be nil or between 0 and 5000.")
}
req, err := client.ListBlobsPreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", nil, "Failure preparing request")
return
}
resp, err := client.ListBlobsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure sending request")
return
}
result, err = client.ListBlobsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure responding to request")
return
}
return
}
// ListBlobsPreparer prepares the ListBlobs request.
func (client Client) ListBlobsPreparer(ctx context.Context, accountName, containerName string, input ListBlobsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "list"),
"restype": autorest.Encode("query", "container"),
}
if input.Delimiter != nil {
queryParameters["delimiter"] = autorest.Encode("query", *input.Delimiter)
}
if input.Include != nil {
vals := make([]string, 0)
for _, v := range *input.Include {
vals = append(vals, string(v))
}
include := strings.Join(vals, ",")
queryParameters["include"] = autorest.Encode("query", include)
}
if input.Marker != nil {
queryParameters["marker"] = autorest.Encode("query", *input.Marker)
}
if input.MaxResults != nil {
queryParameters["maxresults"] = autorest.Encode("query", *input.MaxResults)
}
if input.Prefix != nil {
queryParameters["prefix"] = autorest.Encode("query", *input.Prefix)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListBlobsSender sends the ListBlobs request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListBlobsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListBlobsResponder handles the response to the ListBlobs request. The method always
// closes the http.Response Body.
func (client Client) ListBlobsResponder(resp *http.Response) (result ListBlobsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/models.go 0000664 0000000 0000000 00000003464 14232154237 0023011 0 ustar 00root root 0000000 0000000 package containers
import "github.com/Azure/go-autorest/autorest"
type AccessLevel string
var (
// Blob specifies public read access for blobs.
// Blob data within this container can be read via anonymous request,
// but container data is not available.
// Clients cannot enumerate blobs within the container via anonymous request.
Blob AccessLevel = "blob"
// Container specifies full public read access for container and blob data.
// Clients can enumerate blobs within the container via anonymous request,
// but cannot enumerate containers within the storage account.
Container AccessLevel = "container"
// Private specifies that container data is private to the account owner
Private AccessLevel = ""
)
type ContainerProperties struct {
autorest.Response
AccessLevel AccessLevel
LeaseStatus LeaseStatus
LeaseState LeaseState
LeaseDuration *LeaseDuration
MetaData map[string]string
HasImmutabilityPolicy bool
HasLegalHold bool
}
type Dataset string
var (
Copy Dataset = "copy"
Deleted Dataset = "deleted"
MetaData Dataset = "metadata"
Snapshots Dataset = "snapshots"
UncommittedBlobs Dataset = "uncommittedblobs"
)
type ErrorResponse struct {
Code *string `xml:"Code"`
Message *string `xml:"Message"`
}
type LeaseDuration string
var (
// If this lease is for a Fixed Duration
Fixed LeaseDuration = "fixed"
// If this lease is for an Indefinite Duration
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
giovanni-0.20.0/storage/2019-12-12/blob/containers/resource_id.go 0000664 0000000 0000000 00000003260 14232154237 0024023 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Container
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, containerName)
}
// GetResourceManagerResourceID returns the Resource Manager specific
// ResourceID for a specific Storage Container
func (client Client) GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, containerName string) string {
fmtStr := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/%s/blobServices/default/containers/%s"
return fmt.Sprintf(fmtStr, subscriptionID, resourceGroup, accountName, containerName)
}
type ResourceID struct {
AccountName string
ContainerName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Container Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
containerName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/resource_id_test.go 0000664 0000000 0000000 00000006654 14232154237 0025074 0 ustar 00root root 0000000 0000000 package containers
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestGetResourceManagerResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.GermanCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.PublicCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceManagerResourceID("11112222-3333-4444-5555-666677778888", "group1", "account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource Manager Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected the container name to be `container1` but got %q", actual.ContainerName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/set_acl.go 0000664 0000000 0000000 00000007651 14232154237 0023142 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetAccessControl sets the Access Control for a Container without a Lease ID
func (client Client) SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error) {
return client.SetAccessControlWithLeaseID(ctx, accountName, containerName, "", level)
}
// SetAccessControlWithLeaseID sets the Access Control for a Container using the specified Lease ID
func (client Client) SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`containerName` cannot be an empty string.")
}
req, err := client.SetAccessControlWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, level)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure responding to request")
return
}
return
}
// SetAccessControlWithLeaseIDPreparer prepares the SetAccessControlWithLeaseID request.
func (client Client) SetAccessControlWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "acl"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, level)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlWithLeaseIDSender sends the SetAccessControlWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlWithLeaseIDResponder handles the response to the SetAccessControlWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/set_metadata.go 0000664 0000000 0000000 00000010137 14232154237 0024154 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the specified MetaData on the Container without a Lease ID
func (client Client) SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error) {
return client.SetMetaDataWithLeaseID(ctx, accountName, containerName, "", metaData)
}
// SetMetaDataWithLeaseID sets the specified MetaData on the Container using the specified Lease ID
func (client Client) SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("containers.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataWithLeaseIDPreparer prepares the SetMetaDataWithLeaseID request.
func (client Client) SetMetaDataWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataWithLeaseIDSender sends the SetMetaDataWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataWithLeaseIDResponder handles the response to the SetMetaDataWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/blob/containers/version.go 0000664 0000000 0000000 00000000470 14232154237 0023205 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/ 0000775 0000000 0000000 00000000000 14232154237 0020730 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/ 0000775 0000000 0000000 00000000000 14232154237 0023277 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/README.md 0000664 0000000 0000000 00000004413 14232154237 0024560 0 ustar 00root root 0000000 0000000 ## Data Lake Storage Gen2 File Systems SDK for API version 2019-12-12
This package allows you to interact with the Data Lake Storage Gen2 File Systems API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
### Example Usage
```go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/go-azure-helpers/authentication"
"github.com/hashicorp/go-azure-helpers/sender"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/datalakestore/filesystems"
)
func Example() error {
accountName := "storageaccount1"
fileSystemName := "filesystem1"
builder := &authentication.Builder{
SubscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"),
ClientID: os.Getenv("ARM_CLIENT_ID"),
ClientSecret: os.Getenv("ARM_CLIENT_SECRET"),
TenantID: os.Getenv("ARM_TENANT_ID"),
Environment: os.Getenv("ARM_ENVIRONMENT"),
// Feature Toggles
SupportsClientSecretAuth: true,
}
c, err := builder.Build()
if err != nil {
return fmt.Errorf("Error building AzureRM Client: %s", err)
}
env, err := authentication.DetermineEnvironment(c.Environment)
if err != nil {
return err
}
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, c.TenantID)
if err != nil {
return err
}
// OAuthConfigForTenant returns a pointer, which can be nil.
if oauthConfig == nil {
return fmt.Errorf("Unable to configure OAuthConfig for tenant %s", c.TenantID)
}
sender := sender.BuildSender("AzureRM")
ctx := context.Background()
storageAuth, err := config.GetAuthorizationToken(sender, oauthConfig, "https://storage.azure.com/")
if err != nil {
return fmt.Errorf("Error retrieving Authorization Token")
}
fileSystemsClient := filesystems.NewWithEnvironment(env)
fileSystemsClient.Client.Authorizer = storageAuth
input := filesystems.CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
return fmt.Errorf("Error creating: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/client.go 0000664 0000000 0000000 00000001216 14232154237 0025104 0 ustar 00root root 0000000 0000000 package filesystems
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Data Lake Storage FileSystem
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Data Lake Storage FileSystem client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Data Lake Storage FileSystem client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/create.go 0000664 0000000 0000000 00000006425 14232154237 0025100 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type CreateInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
}
// Create creates a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Create(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`fileSystemName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure responding to request")
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/create_test.go 0000664 0000000 0000000 00000003202 14232154237 0026125 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCreateHasNoTagsByDefault(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 0 {
t.Fatalf("Expected 0 properties by default but got %d", len(props.Properties))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/delete.go 0000664 0000000 0000000 00000005514 14232154237 0025075 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Delete(ctx context.Context, accountName string, fileSystemName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`fileSystemName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure responding to request")
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/helpers.go 0000664 0000000 0000000 00000002041 14232154237 0025265 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"strings"
)
func buildProperties(input map[string]string) string {
// properties has to be a comma-separated key-value pair
properties := make([]string, 0)
for k, v := range input {
properties = append(properties, fmt.Sprintf("%s=%s", k, v))
}
return strings.Join(properties, ",")
}
func parseProperties(input string) (*map[string]string, error) {
properties := make(map[string]string)
if input == "" {
return &properties, nil
}
// properties is a comma-separated list of key-value pairs
splitProperties := strings.Split(input, ",")
for _, propertyRaw := range splitProperties {
// because these are base64-encoded they're likely to end in at least one =
// as such we can't string split on that -_-
position := strings.Index(propertyRaw, "=")
if position < 0 {
return nil, fmt.Errorf("Expected there to be an equals in the key value pair: %q", propertyRaw)
}
key := propertyRaw[0:position]
value := propertyRaw[position+1:]
properties[key] = value
}
return &properties, nil
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/helpers_test.go 0000664 0000000 0000000 00000002724 14232154237 0026334 0 ustar 00root root 0000000 0000000 package filesystems
import (
"reflect"
"testing"
)
func TestParseProperties(t *testing.T) {
testData := []struct {
name string
input string
expected map[string]string
expectError bool
}{
{
name: "no items",
input: "",
expected: map[string]string{},
expectError: false,
},
{
name: "invalid item",
input: "hello",
expectError: true,
},
{
name: "single item",
input: "hello=world",
expected: map[string]string{
"hello": "world",
},
},
{
name: "single-item-base64",
input: "hello=aGVsbG8=",
expected: map[string]string{
"hello": "aGVsbG8=",
},
expectError: false,
},
{
name: "single-item-base64-multipleequals",
input: "hello=d29uZGVybGFuZA==",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
},
expectError: false,
},
{
name: "multiple-items-base64",
input: "hello=d29uZGVybGFuZA==,private=ZXll",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
expectError: false,
},
}
for _, testCase := range testData {
t.Logf("[DEBUG] Test %q", testCase.name)
actual, err := parseProperties(testCase.input)
if err != nil {
if testCase.expectError {
continue
}
t.Fatalf("[DEBUG] Didn't expect an error but got %s", err)
}
if !reflect.DeepEqual(testCase.expected, *actual) {
t.Fatalf("Expected %+v but got %+v", testCase.expected, *actual)
}
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/lifecycle_test.go 0000664 0000000 0000000 00000005302 14232154237 0026624 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{
"hello": "aGVsbG8=",
},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 1 {
t.Fatalf("Expected 1 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "aGVsbG8=" {
t.Fatalf("Expected `hello` to be `aGVsbG8=` but got %q", props.Properties["hello"])
}
t.Logf("[DEBUG] Updating the properties..")
setInput := SetPropertiesInput{
Properties: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
}
if _, err := fileSystemsClient.SetProperties(ctx, accountName, fileSystemName, setInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Properties..")
props, err = fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 2 {
t.Fatalf("Expected 2 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "d29uZGVybGFuZA==" {
t.Fatalf("Expected `hello` to be `d29uZGVybGFuZA==` but got %q", props.Properties["hello"])
}
if props.Properties["private"] != "ZXll" {
t.Fatalf("Expected `private` to be `ZXll` but got %q", props.Properties["private"])
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/properties_get.go 0000664 0000000 0000000 00000007435 14232154237 0026672 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPropertiesResponse struct {
autorest.Response
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Is Hierarchical Namespace Enabled?
NamespaceEnabled bool
}
// GetProperties gets the properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) GetProperties(ctx context.Context, accountName string, fileSystemName string) (result GetPropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure responding to request")
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResponse, err error) {
if resp != nil && resp.Header != nil {
propertiesRaw := resp.Header.Get("x-ms-properties")
var properties *map[string]string
properties, err = parseProperties(propertiesRaw)
if err != nil {
return
}
result.Properties = *properties
result.NamespaceEnabled = strings.EqualFold(resp.Header.Get("x-ms-namespace-enabled"), "tru")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/properties_set.go 0000664 0000000 0000000 00000007773 14232154237 0026713 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has been modified since the specified date and time.
IfModifiedSince *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has not been modified since the specified date and time.
IfUnmodifiedSince *string
}
// SetProperties sets the Properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) SetProperties(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure responding to request")
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
preparer := autorest.CreatePreparer(
autorest.AsPatch(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/resource_id.go 0000664 0000000 0000000 00000002417 14232154237 0026135 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Data Lake Storage FileSystem
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
type ResourceID struct {
AccountName string
DirectoryName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Data Lake Storage FileSystem API's
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.dfs.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
directoryName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/resource_id_test.go 0000664 0000000 0000000 00000003756 14232154237 0027203 0 ustar 00root root 0000000 0000000 package filesystems
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected the directory name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/filesystems/version.go 0000664 0000000 0000000 00000000471 14232154237 0025315 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/ 0000775 0000000 0000000 00000000000 14232154237 0022047 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/client.go 0000664 0000000 0000000 00000001166 14232154237 0023660 0 ustar 00root root 0000000 0000000 package paths
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Data Lake Storage Path
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Data Lake Storage Path client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Data Lake Storage Path client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/create.go 0000664 0000000 0000000 00000006170 14232154237 0023645 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PathResource string
const PathResourceFile PathResource = "file"
const PathResourceDirectory PathResource = "directory"
type CreateInput struct {
Resource PathResource
}
// Create creates a Data Lake Store Gen2 Path within a Storage Account
func (client Client) Create(ctx context.Context, accountName string, fileSystemName string, path string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`fileSystemName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, fileSystemName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure responding to request")
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, fileSystemName string, path string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", input.Resource),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/create_test.go 0000664 0000000 0000000 00000003512 14232154237 0024701 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/datalakestore/filesystems"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCreateDirectory(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
path := "test"
if _, err = client.BuildTestResourcesWithHns(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := filesystems.NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
fileSystemInput := filesystems.CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, fileSystemInput); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Creating path..")
pathsClient := NewWithEnvironment(client.Environment)
pathsClient.Client = client.PrepareWithStorageResourceManagerAuth(pathsClient.Client)
input := CreateInput{
Resource: PathResourceDirectory,
}
if _, err = pathsClient.Create(ctx, accountName, fileSystemName, path, input); err != nil {
t.Fatal(fmt.Errorf("Error creating path: %s", err))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/delete.go 0000664 0000000 0000000 00000005403 14232154237 0023642 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Delete(ctx context.Context, accountName string, fileSystemName string, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`fileSystemName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, fileSystemName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure responding to request")
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, fileSystemName string, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/helpers.go 0000664 0000000 0000000 00000000431 14232154237 0024036 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
)
func parsePathResource(input string) (PathResource, error) {
switch input {
case "file":
return PathResourceFile, nil
case "directory":
return PathResourceDirectory, nil
}
return "", fmt.Errorf("Unhandled path resource type %q", input)
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/lifecycle_test.go 0000664 0000000 0000000 00000007307 14232154237 0025403 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/datalakestore/filesystems"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
const defaultACLString = "user::rwx,group::r-x,other::---"
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
path := "test"
if _, err = client.BuildTestResourcesWithHns(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := filesystems.NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
pathsClient := NewWithEnvironment(client.Environment)
pathsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
fileSystemInput := filesystems.CreateInput{}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, fileSystemInput); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Creating folder 'test' ..")
input := CreateInput{
Resource: PathResourceDirectory,
}
if _, err = pathsClient.Create(ctx, accountName, fileSystemName, path, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' ..")
props, err := pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
t.Logf("[DEBUG] Props.Owner: %q", props.Owner)
t.Logf("[DEBUG] Props.Group: %q", props.Group)
t.Logf("[DEBUG] Props.ACL: %q", props.ACL)
t.Logf("[DEBUG] Props.ETag: %q", props.ETag)
t.Logf("[DEBUG] Props.LastModified: %q", props.LastModified)
if props.ACL != defaultACLString {
t.Fatal(fmt.Errorf("Expected Default ACL %q, got %q", defaultACLString, props.ACL))
}
newACL := "user::rwx,group::r-x,other::r-x,default:user::rwx,default:group::r-x,default:other::---"
accessControlInput := SetAccessControlInput{
ACL: &newACL,
}
t.Logf("[DEBUG] Setting Access Control for folder 'test' ..")
if _, err = pathsClient.SetAccessControl(ctx, accountName, fileSystemName, path, accessControlInput); err != nil {
t.Fatal(fmt.Errorf("Error setting Access Control %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' (2) ..")
props, err = pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties (2): %s", err))
}
if props.ACL != newACL {
t.Fatal(fmt.Errorf("Expected new ACL %q, got %q", newACL, props.ACL))
}
t.Logf("[DEBUG] Deleting path 'test' ..")
if _, err = pathsClient.Delete(ctx, accountName, fileSystemName, path); err != nil {
t.Fatal(fmt.Errorf("Error deleting path: %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' (3) ..")
props, err = pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err == nil {
t.Fatal(fmt.Errorf("Didn't get error getting properties after deleting path (3)"))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting filesystem: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/properties_get.go 0000664 0000000 0000000 00000010721 14232154237 0025432 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPropertiesResponse struct {
autorest.Response
ETag string
LastModified time.Time
// ResourceType is only returned for GetPropertiesActionGetStatus requests
ResourceType PathResource
Owner string
Group string
// ACL is only returned for GetPropertiesActionGetAccessControl requests
ACL string
}
type GetPropertiesAction string
const (
GetPropertiesActionGetStatus GetPropertiesAction = "getStatus"
GetPropertiesActionGetAccessControl GetPropertiesAction = "getAccessControl"
)
// GetProperties gets the properties for a Data Lake Store Gen2 Path in a FileSystem within a Storage Account
func (client Client) GetProperties(ctx context.Context, accountName string, fileSystemName string, path string, action GetPropertiesAction) (result GetPropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, fileSystemName, path, action)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure responding to request")
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string, path string, action GetPropertiesAction) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"action": autorest.Encode("query", string(action)),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResponse, err error) {
result = GetPropertiesResponse{}
if resp != nil && resp.Header != nil {
resourceTypeRaw := resp.Header.Get("x-ms-resource-type")
var resourceType PathResource
if resourceTypeRaw != "" {
resourceType, err = parsePathResource(resourceTypeRaw)
if err != nil {
return GetPropertiesResponse{}, err
}
result.ResourceType = resourceType
}
result.ETag = resp.Header.Get("ETag")
if lastModifiedRaw := resp.Header.Get("Last-Modified"); lastModifiedRaw != "" {
lastModified, err := time.Parse(time.RFC1123, lastModifiedRaw)
if err != nil {
return GetPropertiesResponse{}, err
}
result.LastModified = lastModified
}
result.Owner = resp.Header.Get("x-ms-owner")
result.Group = resp.Header.Get("x-ms-group")
result.ACL = resp.Header.Get("x-ms-acl")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return result, err
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/properties_set.go 0000664 0000000 0000000 00000010024 14232154237 0025442 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetAccessControlInput struct {
Owner *string
Group *string
ACL *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has been modified since the specified date and time.
IfModifiedSince *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has not been modified since the specified date and time.
IfUnmodifiedSince *string
}
// SetProperties sets the access control properties for a Data Lake Store Gen2 Path within a Storage Account File System
func (client Client) SetAccessControl(ctx context.Context, accountName string, fileSystemName string, path string, input SetAccessControlInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "SetAccessControl", "`fileSystemName` cannot be an empty string.")
}
req, err := client.SetAccessControlPreparer(ctx, accountName, fileSystemName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", resp, "Failure responding to request")
}
return
}
// SetAccessControlPreparer prepares the SetAccessControl request.
func (client Client) SetAccessControlPreparer(ctx context.Context, accountName string, fileSystemName string, path string, input SetAccessControlInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"action": autorest.Encode("query", "setAccessControl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.Owner != nil {
headers["x-ms-owner"] = *input.Owner
}
if input.Group != nil {
headers["x-ms-group"] = *input.Group
}
if input.ACL != nil {
headers["x-ms-acl"] = *input.ACL
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
preparer := autorest.CreatePreparer(
autorest.AsPatch(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlSender sends the SetAccessControl request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlResponder handles the response to the SetAccessControl request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/resource_id.go 0000664 0000000 0000000 00000003140 14232154237 0024677 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Data Lake Storage FileSystem
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, fileSystemName, path string) string {
domain := endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, fileSystemName, path)
}
type ResourceID struct {
AccountName string
FileSystemName string
Path string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Data Lake Storage FileSystem API's
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.dfs.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
fileSystemAndPath := strings.TrimPrefix(uri.Path, "/")
separatorIndex := strings.Index(fileSystemAndPath, "/")
var fileSystem, path string
if separatorIndex < 0 {
fileSystem = fileSystemAndPath
path = ""
} else {
fileSystem = fileSystemAndPath[0:separatorIndex]
path = fileSystemAndPath[separatorIndex+1:]
}
return &ResourceID{
AccountName: *accountName,
FileSystemName: fileSystem,
Path: path,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/resource_id_test.go 0000664 0000000 0000000 00000004353 14232154237 0025745 0 ustar 00root root 0000000 0000000 package paths
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
AccountName string
FileSystemName string
Path string
Expected string
}{
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "test",
Expected: "https://account1.dfs.core.windows.net/fs1/test",
},
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "test/test2",
Expected: "https://account1.dfs.core.windows.net/fs1/test/test2",
},
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "",
Expected: "https://account1.dfs.core.windows.net/fs1/",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Path %q", v.Path)
c := NewWithEnvironment(azure.PublicCloud)
actual := c.GetResourceID(v.AccountName, v.FileSystemName, v.Path)
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Input string
AccountName string
FileSystemName string
Path string
}{
{
Input: "https://account1.dfs.core.windows.net/fs1/test",
AccountName: "account1",
FileSystemName: "fs1",
Path: "test",
},
{
Input: "https://account1.dfs.core.windows.net/fs1/test/test2",
AccountName: "account1",
FileSystemName: "fs1",
Path: "test/test2",
},
{
Input: "https://account1.dfs.core.windows.net/fs1/",
AccountName: "account1",
FileSystemName: "fs1",
Path: "",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Path %q", v.Path)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != v.AccountName {
t.Fatalf("Expected the account name to be `%q` but got %q", v.AccountName, actual.AccountName)
}
if actual.FileSystemName != v.FileSystemName {
t.Fatalf("Expected the file system name to be `%q` but got %q", v.FileSystemName, actual.FileSystemName)
}
if actual.Path != v.Path {
t.Fatalf("Expected the path to be `%q` but got %q", v.Path, actual.Path)
}
}
}
giovanni-0.20.0/storage/2019-12-12/datalakestore/paths/version.go 0000664 0000000 0000000 00000000463 14232154237 0024066 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/file/ 0000775 0000000 0000000 00000000000 14232154237 0017024 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/file/directories/ 0000775 0000000 0000000 00000000000 14232154237 0021340 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/file/directories/README.md 0000664 0000000 0000000 00000002364 14232154237 0022624 0 ustar 00root root 0000000 0000000 ## File Storage Directories SDK for API version 2019-12-12
This package allows you to interact with the Directories File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Limitations
* At this time the headers `x-ms-file-permission` and `x-ms-file-attributes` are hard-coded (to `inherit` and `None`, respectively).
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/directories"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
directoriesClient := directories.New()
directoriesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := directoriesClient.Create(ctx, accountName, shareName, directoryName, metadata); err != nil {
return fmt.Errorf("Error creating Directory: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/file/directories/api.go 0000664 0000000 0000000 00000001375 14232154237 0022446 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageDirectory interface {
Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error)
SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName, path string, input CreateDirectoryInput) (result autorest.Response, err error)
GetResourceID(accountName, shareName, directoryName string) string
Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error)
}
giovanni-0.20.0/storage/2019-12-12/file/directories/client.go 0000664 0000000 0000000 00000001132 14232154237 0023142 0 ustar 00root root 0000000 0000000 package directories
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/file/directories/create.go 0000664 0000000 0000000 00000011273 14232154237 0023136 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateDirectoryInput struct {
// The time at which this file was created at - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-creation-time` field.
// ... Yes I know it says File not Directory, I didn't design the API.
CreatedAt *time.Time
// The time at which this file was last modified - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-last-write-time` field.
// ... Yes I know it says File not Directory, I didn't design the API.
LastModified *time.Time
// MetaData is a mapping of key value pairs which should be assigned to this directory
MetaData map[string]string
}
// Create creates a new directory under the specified share or parent directory.
func (client Client) Create(ctx context.Context, accountName, shareName, path string, input CreateDirectoryInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Create", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Create", "`path` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("directories.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path string, input CreateDirectoryInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
var coalesceDate = func(input *time.Time, defaultVal string) string {
if input == nil {
return defaultVal
}
return input.Format(time.RFC1123)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// ... Yes I know these say File not Directory, I didn't design the API.
"x-ms-file-permission": "inherit", // TODO: expose this in future
"x-ms-file-attributes": "None", // TODO: expose this in future
"x-ms-file-creation-time": coalesceDate(input.CreatedAt, "now"),
"x-ms-file-last-write-time": coalesceDate(input.LastModified, "now"),
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/directories/delete.go 0000664 0000000 0000000 00000006343 14232154237 0023137 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete removes the specified empty directory
// Note that the directory must be empty before it can be deleted.
func (client Client) Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Delete", "`path` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/directories/get.go 0000664 0000000 0000000 00000007432 14232154237 0022454 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
// A set of name-value pairs that contain metadata for the directory.
MetaData map[string]string
// The value of this header is set to true if the directory metadata is completely
// encrypted using the specified algorithm. Otherwise, the value is set to false.
DirectoryMetaDataEncrypted bool
}
// Get returns all system properties for the specified directory,
// and can also be used to check the existence of a directory.
func (client Client) Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Get", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Get", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Get", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Get", "`path` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
result.DirectoryMetaDataEncrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/directories/lifecycle_test.go 0000664 0000000 0000000 00000007447 14232154237 0024701 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var StorageFile = Client{}
func TestDirectoriesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
directoriesClient := NewWithEnvironment(client.Environment)
directoriesClient.Client = client.PrepareWithAuthorizer(directoriesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, true)
metaData := map[string]string{
"hello": "world",
}
log.Printf("[DEBUG] Creating Top Level..")
createInput := CreateDirectoryInput{
MetaData: metaData,
}
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello", createInput); err != nil {
t.Fatalf("Error creating Top Level Directory: %s", err)
}
log.Printf("[DEBUG] Creating Inner..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello/there", createInput); err != nil {
t.Fatalf("Error creating Inner Directory: %s", err)
}
log.Printf("[DEBUG] Retrieving share")
innerDir, err := directoriesClient.Get(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving Inner Directory: %s", err)
}
if innerDir.DirectoryMetaDataEncrypted != true {
t.Fatalf("Expected MetaData to be encrypted but got: %t", innerDir.DirectoryMetaDataEncrypted)
}
if len(innerDir.MetaData) != 1 {
t.Fatalf("Expected MetaData to contain 1 item but got %d", len(innerDir.MetaData))
}
if innerDir.MetaData["hello"] != "world" {
t.Fatalf("Expected MetaData `hello` to be `world`: %s", innerDir.MetaData["hello"])
}
log.Printf("[DEBUG] Setting MetaData")
updatedMetaData := map[string]string{
"panda": "pops",
}
if _, err := directoriesClient.SetMetaData(ctx, accountName, shareName, "hello/there", updatedMetaData); err != nil {
t.Fatalf("Error updating MetaData: %s", err)
}
log.Printf("[DEBUG] Retrieving MetaData")
retrievedMetaData, err := directoriesClient.GetMetaData(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving the updated metadata: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected the updated metadata to have 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["panda"] != "pops" {
t.Fatalf("Expected the metadata `panda` to be `pops` but got %q", retrievedMetaData.MetaData["panda"])
}
t.Logf("[DEBUG] Deleting Inner..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello/there"); err != nil {
t.Fatalf("Error deleting Inner Directory: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello"); err != nil {
t.Fatalf("Error deleting Top Level Directory: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/file/directories/metadata_get.go 0000664 0000000 0000000 00000007127 14232154237 0024315 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns all user-defined metadata for the specified directory
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`path` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/directories/metadata_set.go 0000664 0000000 0000000 00000007273 14232154237 0024333 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates user defined metadata for the specified directory
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/directories/resource_id.go 0000664 0000000 0000000 00000003113 14232154237 0024170 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Directory
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, shareName, directoryName)
}
type ResourceID struct {
AccountName string
DirectoryName string
ShareName string
}
// ParseResourceID parses the Resource ID into an Object
// which can be used to interact with the Directory within the File Share
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar/Folder
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/file/directories/resource_id_test.go 0000664 0000000 0000000 00000004246 14232154237 0025237 0 ustar 00root root 0000000 0000000 package directories
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/file/directories/version.go 0000664 0000000 0000000 00000000471 14232154237 0023356 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/file/files/ 0000775 0000000 0000000 00000000000 14232154237 0020126 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/file/files/README.md 0000664 0000000 0000000 00000002313 14232154237 0021404 0 ustar 00root root 0000000 0000000 ## File Storage Files SDK for API version 2019-12-12
This package allows you to interact with the Files File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Limitations
* At this time the headers `x-ms-file-permission` and `x-ms-file-attributes` are hard-coded (to `inherit` and `None`, respectively).
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/files"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
fileName := "example.txt"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
filesClient := files.New()
filesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := files.CreateInput{}
if _, err := filesClient.Create(ctx, accountName, shareName, directoryName, fileName, input); err != nil {
return fmt.Errorf("Error creating File: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/file/files/api.go 0000664 0000000 0000000 00000004234 14232154237 0021231 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
)
type StorageFile interface {
PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error)
GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error)
ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error)
SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error)
PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error
Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error)
SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error)
AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error)
GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error)
GetResourceID(accountName, shareName, directoryName, filePath string) string
ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error)
GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error)
Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error)
CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error)
}
giovanni-0.20.0/storage/2019-12-12/file/files/client.go 0000664 0000000 0000000 00000001124 14232154237 0021731 0 ustar 00root root 0000000 0000000 package files
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/file/files/copy.go 0000664 0000000 0000000 00000011216 14232154237 0021430 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the URL of the source file or blob, up to 2 KB in length.
//
// To copy a file to another file within the same storage account, you may use Shared Key to authenticate
// the source file. If you are copying a file from another storage account, or if you are copying a blob from
// the same storage account or another storage account, then you must authenticate the source file or blob using a
// shared access signature. If the source is a public blob, no authentication is required to perform the copy
// operation. A file in a share snapshot can also be specified as a copy source.
CopySource string
MetaData map[string]string
}
type CopyResult struct {
autorest.Response
// The CopyID, which can be passed to AbortCopy to abort the copy.
CopyID string
// Either `success` or `pending`
CopySuccess string
}
// Copy copies a blob or file to a destination file within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Copy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Copy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Copy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Copy", "`fileName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("files.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Copy", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CopyPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopySuccess = resp.Header.Get("x-ms-copy-status")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/copy_abort.go 0000664 0000000 0000000 00000007157 14232154237 0022630 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// AbortCopy aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata
func (client Client) AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`fileName` cannot be an empty string.")
}
if copyID == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`copyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, shareName, path, fileName, copyID)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, shareName, path, fileName, copyID string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", copyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/copy_wait.go 0000664 0000000 0000000 00000002414 14232154237 0022454 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
)
type CopyAndWaitResult struct {
autorest.Response
CopyID string
}
const DefaultCopyPollDuration = 15 * time.Second
// CopyAndWait is a convenience method which doesn't exist in the API, which copies the file and then waits for the copy to complete
func (client Client) CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error) {
copy, e := client.Copy(ctx, accountName, shareName, path, fileName, input)
if err != nil {
result.Response = copy.Response
err = fmt.Errorf("Error copying: %s", e)
return
}
result.CopyID = copy.CopyID
// since the API doesn't return a LRO, this is a hack which also polls every 10s, but should be sufficient
for true {
props, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if e != nil {
result.Response = copy.Response
err = fmt.Errorf("Error waiting for copy: %s", e)
return
}
switch strings.ToLower(props.CopyStatus) {
case "pending":
time.Sleep(pollDuration)
continue
case "success":
return
default:
err = fmt.Errorf("Unexpected CopyState %q", e)
return
}
}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/copy_wait_test.go 0000664 0000000 0000000 00000011043 14232154237 0023511 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestFilesCopyAndWaitFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
copiedFileName := "ubuntu.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
func TestFilesCopyAndWaitFromBlob(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
originalFileName := "ubuntu.iso"
copiedFileName := "ubuntu-copied.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting the original file..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", originalFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Now copying that blob..")
duplicateInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetFileEndpoint(filesClient.BaseURI, accountName), shareName, originalFileName),
}
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, duplicateInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copying duplicate: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
giovanni-0.20.0/storage/2019-12-12/file/files/create.go 0000664 0000000 0000000 00000013074 14232154237 0021725 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// This header specifies the maximum size for the file, up to 1 TiB.
ContentLength int64
// The MIME content type of the file
// If not specified, the default type is application/octet-stream.
ContentType *string
// Specifies which content encodings have been applied to the file.
// This value is returned to the client when the Get File operation is performed
// on the file resource and can be used to decode file content.
ContentEncoding *string
// Specifies the natural languages used by this resource.
ContentLanguage *string
// The File service stores this value but does not use or modify it.
CacheControl *string
// Sets the file's MD5 hash.
ContentMD5 *string
// Sets the file’s Content-Disposition header.
ContentDisposition *string
// The time at which this file was created at - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-creation-time` field.
CreatedAt *time.Time
// The time at which this file was last modified - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-last-write-time` field.
LastModified *time.Time
// MetaData is a mapping of key value pairs which should be assigned to this file
MetaData map[string]string
}
// Create creates a new file or replaces a file.
func (client Client) Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Create", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Create", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Create", "`input.MetaData` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
var coalesceDate = func(input *time.Time, defaultVal string) string {
if input == nil {
return defaultVal
}
return input.Format(time.RFC1123)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-content-length": input.ContentLength,
"x-ms-type": "file",
"x-ms-file-permission": "inherit", // TODO: expose this in future
"x-ms-file-attributes": "None", // TODO: expose this in future
"x-ms-file-creation-time": coalesceDate(input.CreatedAt, "now"),
"x-ms-file-last-write-time": coalesceDate(input.LastModified, "now"),
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/delete.go 0000664 0000000 0000000 00000006206 14232154237 0021723 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete immediately deletes the file from the File Share.
func (client Client) Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Delete", "`fileName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/lifecycle_test.go 0000664 0000000 0000000 00000012406 14232154237 0023456 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageFile = Client{}
func TestFilesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
fileName := "bled5.png"
contentEncoding := "application/vnd+panda"
t.Logf("[DEBUG] Creating Top Level File..")
createInput := CreateInput{
ContentLength: 1024,
ContentEncoding: &contentEncoding,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Top-Level File..")
file, err := filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 1024 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != contentEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", contentEncoding, file.ContentEncoding)
}
updatedSize := int64(2048)
updatedEncoding := "application/vnd+pandas2"
updatedInput := SetPropertiesInput{
ContentEncoding: &updatedEncoding,
ContentLength: updatedSize,
MetaData: map[string]string{
"bingo": "bango",
},
}
t.Logf("[DEBUG] Setting Properties for the Top-Level File..")
if _, err := filesClient.SetProperties(ctx, accountName, shareName, "", fileName, updatedInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Properties for the Top-Level File..")
file, err = filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 2048 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != updatedEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", updatedEncoding, file.ContentEncoding)
}
if len(file.MetaData) != 1 {
t.Fatalf("Expected 1 item but got %d", len(file.MetaData))
}
if file.MetaData["bingo"] != "bango" {
t.Fatalf("Expected `bingo` to be `bango` but got %q", file.MetaData["bingo"])
}
t.Logf("[DEBUG] Setting MetaData..")
metaData := map[string]string{
"hello": "there",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Retrieving MetaData..")
retrievedMetaData, err := filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
t.Logf("[DEBUG] Re-Setting MetaData..")
metaData = map[string]string{
"hello": "there",
"second": "thing",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving MetaData..")
retrievedMetaData, err = filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 2 {
t.Fatalf("Expected 2 items but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
if retrievedMetaData.MetaData["second"] != "thing" {
t.Fatalf("Expected `second` to be `thing` but got %q", retrievedMetaData.MetaData["second"])
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/file/files/metadata_get.go 0000664 0000000 0000000 00000007263 14232154237 0023104 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData for the specified File.
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`fileName` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
//metadata.ByParsingFromHeaders(&result.MetaData),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/metadata_set.go 0000664 0000000 0000000 00000007347 14232154237 0023123 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates the specified File to have the specified MetaData.
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("files.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, fileName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/properties_get.go 0000664 0000000 0000000 00000012141 14232154237 0023507 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
CacheControl string
ContentDisposition string
ContentEncoding string
ContentLanguage string
ContentLength *int64
ContentMD5 string
ContentType string
CopyID string
CopyStatus string
CopySource string
CopyProgress string
CopyStatusDescription string
CopyCompletionTime string
Encrypted bool
MetaData map[string]string
}
// GetProperties returns the Properties for the specified file
func (client Client) GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = resp.Header.Get("x-ms-copy-status")
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.Encrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
contentLengthRaw := resp.Header.Get("Content-Length")
if contentLengthRaw != "" {
contentLength, err := strconv.Atoi(contentLengthRaw)
if err != nil {
return result, fmt.Errorf("Error parsing %q for Content-Length as an integer: %s", contentLengthRaw, err)
}
contentLengthI64 := int64(contentLength)
result.ContentLength = &contentLengthI64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/properties_set.go 0000664 0000000 0000000 00000015641 14232154237 0023533 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SetPropertiesInput struct {
// Resizes a file to the specified size.
// If the specified byte value is less than the current size of the file,
// then all ranges above the specified byte value are cleared.
ContentLength int64
// Modifies the cache control string for the file.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentControl *string
// Sets the file’s Content-Disposition header.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentDisposition *string
// Sets the file's content encoding.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentEncoding *string
// Sets the file's content language.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentLanguage *string
// Sets the file's MD5 hash.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentMD5 *string
// Sets the file's content type.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentType *string
// The time at which this file was created at - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-creation-time` field.
CreatedAt *time.Time
// The time at which this file was last modified - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-last-write-time` field.
LastModified *time.Time
// MetaData is a mapping of key value pairs which should be assigned to this file
MetaData map[string]string
}
// SetProperties sets the specified properties on the specified File
func (client Client) SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
var coalesceDate = func(input *time.Time, defaultVal string) string {
if input == nil {
return defaultVal
}
return input.Format(time.RFC1123)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-type": "file",
"x-ms-content-length": input.ContentLength,
"x-ms-file-permission": "inherit", // TODO: expose this in future
"x-ms-file-attributes": "None", // TODO: expose this in future
"x-ms-file-creation-time": coalesceDate(input.CreatedAt, "now"),
"x-ms-file-last-write-time": coalesceDate(input.LastModified, "now"),
}
if input.ContentControl != nil {
headers["x-ms-cache-control"] = *input.ContentControl
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/range_clear.go 0000664 0000000 0000000 00000007740 14232154237 0022727 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ClearByteRangeInput struct {
StartBytes int64
EndBytes int64
}
// ClearByteRange clears the specified Byte Range from within the specified File
func (client Client) ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.EndBytes` must be greater than 0.")
}
req, err := client.ClearByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", nil, "Failure preparing request")
return
}
resp, err := client.ClearByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure sending request")
return
}
result, err = client.ClearByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure responding to request")
return
}
return
}
// ClearByteRangePreparer prepares the ClearByteRange request.
func (client Client) ClearByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes),
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ClearByteRangeSender sends the ClearByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ClearByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ClearByteRangeResponder handles the response to the ClearByteRange request. The method always
// closes the http.Response Body.
func (client Client) ClearByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/range_get.go 0000664 0000000 0000000 00000010430 14232154237 0022406 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetByteRangeInput struct {
StartBytes int64
EndBytes int64
}
type GetByteRangeResult struct {
autorest.Response
Contents []byte
}
// GetByteRange returns the specified Byte Range from the specified File.
func (client Client) GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at most 4MB.")
}
req, err := client.GetByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", nil, "Failure preparing request")
return
}
resp, err := client.GetByteRangeSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure sending request")
return
}
result, err = client.GetByteRangeResponder(resp, expectedBytes)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure responding to request")
return
}
return
}
// GetByteRangePreparer prepares the GetByteRange request.
func (client Client) GetByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetByteRangeSender sends the GetByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetByteRangeResponder handles the response to the GetByteRange request. The method always
// closes the http.Response Body.
func (client Client) GetByteRangeResponder(resp *http.Response, length int64) (result GetByteRangeResult, err error) {
result.Contents = make([]byte, length)
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/range_get_file.go 0000664 0000000 0000000 00000006055 14232154237 0023415 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"log"
"math"
"runtime"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// GetFile is a helper method to download a file by chunking it automatically
func (client Client) GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error) {
// first look up the file and check out how many bytes it is
file, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if err != nil {
result = file.Response
err = e
return
}
if file.ContentLength == nil {
err = fmt.Errorf("Content-Length was nil!")
return
}
length := int64(*file.ContentLength)
chunkSize := int64(4 * 1024 * 1024) // 4MB
if chunkSize > length {
chunkSize = length
}
// then split that up into chunks and retrieve it retrieve it into the 'results' set
chunks := int(math.Ceil(float64(length) / float64(chunkSize)))
workerCount := parallelism * runtime.NumCPU()
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
results := make([]*downloadFileChunkResult, chunks)
errors := make(chan error, chunkSize)
for i := 0; i < chunks; i++ {
go func(i int) {
log.Printf("[DEBUG] Downloading Chunk %d of %d", i+1, chunks)
dfci := downloadFileChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: length,
}
result, err := client.downloadFileChunk(ctx, accountName, shareName, path, fileName, dfci)
if err != nil {
errors <- err
waitGroup.Done()
return
}
// if there's no error, we should have bytes, so this is safe
results[i] = result
waitGroup.Done()
}(i)
}
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
err = fmt.Errorf("Error downloading file: %s", <-errors)
return
}
// then finally put it all together, in order and return it
output := make([]byte, length)
for _, v := range results {
copy(output[v.startBytes:v.endBytes], v.bytes)
}
outputBytes = output
return
}
type downloadFileChunkInput struct {
thisChunk int
chunkSize int64
fileSize int64
}
type downloadFileChunkResult struct {
startBytes int64
endBytes int64
bytes []byte
}
func (client Client) downloadFileChunk(ctx context.Context, accountName, shareName, path, fileName string, input downloadFileChunkInput) (*downloadFileChunkResult, error) {
startBytes := input.chunkSize * int64(input.thisChunk)
endBytes := startBytes + input.chunkSize
// the last chunk may exceed the size of the file
remaining := input.fileSize - startBytes
if input.chunkSize > remaining {
endBytes = startBytes + remaining
}
getInput := GetByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
}
result, err := client.GetByteRange(ctx, accountName, shareName, path, fileName, getInput)
if err != nil {
return nil, fmt.Errorf("Error putting bytes: %s", err)
}
output := downloadFileChunkResult{
startBytes: startBytes,
endBytes: endBytes,
bytes: result.Contents,
}
return &output, nil
}
giovanni-0.20.0/storage/2019-12-12/file/files/range_get_file_test.go 0000664 0000000 0000000 00000007063 14232154237 0024454 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestGetSmallFile(t *testing.T) {
// the purpose of this test is to verify that the small, single-chunked file gets downloaded correctly
testGetFile(t, "small-file.png", "image/png")
}
func TestGetLargeFile(t *testing.T) {
// the purpose of this test is to verify that the large, multi-chunked file gets downloaded correctly
testGetFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testGetFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Downloading file..")
_, downloadedBytes, err := filesClient.GetFile(ctx, accountName, shareName, "", fileName, 4)
if err != nil {
t.Fatalf("Error downloading file: %s", err)
}
t.Logf("[DEBUG] Asserting the files are the same size..")
expectedBytes := make([]byte, info.Size())
file.Read(expectedBytes)
if len(expectedBytes) != len(downloadedBytes) {
t.Fatalf("Expected %d bytes but got %d", len(expectedBytes), len(downloadedBytes))
}
t.Logf("[DEBUG] Asserting the files are the same content-wise..")
// overkill, but it's this or shasum-ing
for i := int64(0); i < info.Size(); i++ {
if expectedBytes[i] != downloadedBytes[i] {
t.Fatalf("Expected byte %d to be %q but got %q", i, expectedBytes[i], downloadedBytes[i])
}
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/file/files/range_put.go 0000664 0000000 0000000 00000010777 14232154237 0022455 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutByteRangeInput struct {
StartBytes int64
EndBytes int64
// Content is the File Contents for the specified range
// which can be at most 4MB
Content []byte
}
// PutByteRange puts the specified Byte Range in the specified File.
func (client Client) PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
actualBytes := len(input.Content)
if expectedBytes != int64(actualBytes) {
return result, validation.NewError("files.Client", "PutByteRange", fmt.Sprintf("The specified byte-range (%d) didn't match the content size (%d).", expectedBytes, actualBytes))
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at most 4MB.")
}
req, err := client.PutByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", nil, "Failure preparing request")
return
}
resp, err := client.PutByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure sending request")
return
}
result, err = client.PutByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure responding to request")
return
}
return
}
// PutByteRangePreparer prepares the PutByteRange request.
func (client Client) PutByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
"Content-Length": int(len(input.Content)),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutByteRangeSender sends the PutByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutByteRangeResponder handles the response to the PutByteRange request. The method always
// closes the http.Response Body.
func (client Client) PutByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/range_put_file.go 0000664 0000000 0000000 00000005070 14232154237 0023442 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"io"
"log"
"math"
"os"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// PutFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
chunkSize := 4 * 1024 * 1024 // 4MB
if chunkSize > int(fileSize) {
chunkSize = int(fileSize)
}
chunks := int(math.Ceil(float64(fileSize) / float64(chunkSize*1.0)))
workerCount := parallelism
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
jobs := make(chan int, workerCount)
errors := make(chan error, chunkSize)
for i := 0; i < workerCount; i++ {
go func() {
for i := range jobs {
log.Printf("[DEBUG] Chunk %d of %d", i+1, chunks)
uci := uploadChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: fileSize,
}
_, err := client.uploadChunk(ctx, accountName, shareName, path, fileName, uci, file)
if err != nil {
errors <- err
}
}
waitGroup.Done()
}()
}
for i := 0; i < chunks; i++ {
jobs <- i
}
close(jobs)
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
return fmt.Errorf("Error uploading file: %s", <-errors)
}
return nil
}
type uploadChunkInput struct {
thisChunk int
chunkSize int
fileSize int64
}
func (client Client) uploadChunk(ctx context.Context, accountName, shareName, path, fileName string, input uploadChunkInput, file *os.File) (result autorest.Response, err error) {
startBytes := int64(input.chunkSize * input.thisChunk)
endBytes := startBytes + int64(input.chunkSize)
// the last size may exceed the size of the file
remaining := input.fileSize - startBytes
if int64(input.chunkSize) > remaining {
endBytes = startBytes + remaining
}
bytesToRead := int(endBytes) - int(startBytes)
bytes := make([]byte, bytesToRead)
_, err = file.ReadAt(bytes, startBytes)
if err != nil {
if err != io.EOF {
return result, fmt.Errorf("Error reading bytes: %s", err)
}
}
putBytesInput := PutByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
Content: bytes,
}
result, err = client.PutByteRange(ctx, accountName, shareName, path, fileName, putBytesInput)
if err != nil {
return result, fmt.Errorf("Error putting bytes: %s", err)
}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/range_put_file_test.go 0000664 0000000 0000000 00000005712 14232154237 0024504 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPutSmallFile(t *testing.T) {
// the purpose of this test is to ensure that a small file (< 4MB) is a single chunk
testPutFile(t, "small-file.png", "image/png")
}
func TestPutLargeFile(t *testing.T) {
// the purpose of this test is to ensure that large files (> 4MB) are chunked
testPutFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func TestPutVerySmallFile(t *testing.T) {
// the purpose of this test is to ensure that a very small file (< 4KB) is a single chunk
testPutFile(t, "very-small.json", "application/json")
}
func testPutFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/file/files/ranges_list.go 0000664 0000000 0000000 00000007277 14232154237 0023004 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListRangesResult struct {
autorest.Response
Ranges []Range `xml:"Range"`
}
type Range struct {
Start string `xml:"Start"`
End string `xml:"End"`
}
// ListRanges returns the list of valid ranges for the specified File.
func (client Client) ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("files.Client", "ListRanges", "`path` cannot be an empty string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`fileName` cannot be an empty string.")
}
req, err := client.ListRangesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", nil, "Failure preparing request")
return
}
resp, err := client.ListRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure sending request")
return
}
result, err = client.ListRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure responding to request")
return
}
return
}
// ListRangesPreparer prepares the ListRanges request.
func (client Client) ListRangesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "rangelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListRangesSender sends the ListRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListRangesResponder handles the response to the ListRanges request. The method always
// closes the http.Response Body.
func (client Client) ListRangesResponder(resp *http.Response) (result ListRangesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/files/resource_id.go 0000664 0000000 0000000 00000003654 14232154237 0022770 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName, filePath string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s/%s", domain, shareName, directoryName, filePath)
}
type ResourceID struct {
AccountName string
DirectoryName string
FileName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with Files within a Storage Share.
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
fileName := segments[len(segments)-1]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
directoryName = strings.TrimSuffix(directoryName, fileName)
directoryName = strings.TrimSuffix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
FileName: fileName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/file/files/resource_id_test.go 0000664 0000000 0000000 00000007430 14232154237 0024023 0 ustar 00root root 0000000 0000000 package files
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1", "file1.txt")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/directory2/file1.txt",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1/directory2" {
t.Fatalf("Expected Directory Name to be `directory1/directory2` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/file/files/version.go 0000664 0000000 0000000 00000000463 14232154237 0022145 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/file/shares/ 0000775 0000000 0000000 00000000000 14232154237 0020311 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/file/shares/README.md 0000664 0000000 0000000 00000001777 14232154237 0021604 0 ustar 00root root 0000000 0000000 ## File Storage Shares SDK for API version 2019-12-12
This package allows you to interact with the Shares File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/file/shares"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
sharesClient := shares.New()
sharesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := shares.CreateInput{
QuotaInGB: 2,
}
if _, err := sharesClient.Create(ctx, accountName, shareName, input); err != nil {
return fmt.Errorf("Error creating Share: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/file/shares/acl_get.go 0000664 0000000 0000000 00000006213 14232154237 0022240 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL get the Access Control List for the specified Storage Share
func (client Client) GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.GetACLPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/acl_set.go 0000664 0000000 0000000 00000006415 14232154237 0022260 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"encoding/xml"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List on the specified Storage Share
func (client Client) SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.SetACLPreparer(ctx, accountName, shareName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/api.go 0000664 0000000 0000000 00000003205 14232154237 0021411 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageShare interface {
SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error)
GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error)
GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error)
GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error)
SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error)
SetProperties(ctx context.Context, accountName, shareName string, newQuotaGB int) (result autorest.Response, err error)
DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error)
CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error)
GetResourceID(accountName, shareName string) string
GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, shareName string) string
GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error)
Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2019-12-12/file/shares/client.go 0000664 0000000 0000000 00000001125 14232154237 0022115 0 ustar 00root root 0000000 0000000 package shares
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/file/shares/create.go 0000664 0000000 0000000 00000007365 14232154237 0022116 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies the maximum size of the share, in gigabytes.
// Must be greater than 0, and less than or equal to 5TB (5120).
QuotaInGB int
MetaData map[string]string
}
// Create creates the specified Storage Share within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Create", "`shareName` must be a lower-cased string.")
}
if input.QuotaInGB <= 0 || input.QuotaInGB > 102400 {
return result, validation.NewError("shares.Client", "Create", "`input.QuotaInGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": input.QuotaInGB,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/delete.go 0000664 0000000 0000000 00000006120 14232154237 0022101 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Storage Share from within a Storage Account
func (client Client) Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Delete", "`shareName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, deleteSnapshots)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if deleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/lifecycle_test.go 0000664 0000000 0000000 00000021030 14232154237 0023632 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageShare = Client{}
func TestSharesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 5)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 5 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
func TestSharesLifecycleLargeQuota(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResourcesWithSku(ctx, resourceGroup, accountName, storage.KindFileStorage, storage.SkuNamePremiumLRS)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1001,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 1001 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.ShareQuota)
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, 6000)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.ShareQuota != 6000 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.ShareQuota)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/file/shares/metadata_get.go 0000664 0000000 0000000 00000006525 14232154237 0023267 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData associated with the specified Storage Share
func (client Client) GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/metadata_set.go 0000664 0000000 0000000 00000006703 14232154237 0023301 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the MetaData on the specified Storage Share
func (client Client) SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("shares.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/models.go 0000664 0000000 0000000 00000000416 14232154237 0022124 0 ustar 00root root 0000000 0000000 package shares
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2019-12-12/file/shares/properties_get.go 0000664 0000000 0000000 00000007150 14232154237 0023676 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesResult struct {
autorest.Response
MetaData map[string]string
ShareQuota int
}
// GetProperties returns the properties about the specified Storage Share
func (client Client) GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
quotaRaw := resp.Header.Get("x-ms-share-quota")
if quotaRaw != "" {
quota, e := strconv.Atoi(quotaRaw)
if e != nil {
return result, fmt.Errorf("Error converting %q to an integer: %s", quotaRaw, err)
}
result.ShareQuota = quota
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/properties_set.go 0000664 0000000 0000000 00000006617 14232154237 0023721 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetProperties lets you update the Quota for the specified Storage Share
func (client Client) SetProperties(ctx context.Context, accountName, shareName string, newQuotaGB int) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if newQuotaGB <= 0 || newQuotaGB > 102400 {
return result, validation.NewError("shares.Client", "SetProperties", "`newQuotaGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, newQuotaGB)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName string, quotaGB int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": quotaGB,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/resource_id.go 0000664 0000000 0000000 00000003217 14232154237 0023146 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File Share
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
// GetResourceManagerResourceID returns the Resource Manager specific
// ResourceID for a specific Storage Share
func (client Client) GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, shareName string) string {
fmtStr := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/%s/fileServices/default/shares/%s"
return fmt.Sprintf(fmtStr, subscriptionID, resourceGroup, accountName, shareName)
}
type ResourceID struct {
AccountName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Storage Shares SDK
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
shareName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/file/shares/resource_id_test.go 0000664 0000000 0000000 00000006514 14232154237 0024210 0 ustar 00root root 0000000 0000000 package shares
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestGetResourceManagerResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.GermanCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.PublicCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceManagerResourceID("11112222-3333-4444-5555-666677778888", "group1", "account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource Manager Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected the share name to be `share1` but got %q", actual.ShareName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/file/shares/snapshot_create.go 0000664 0000000 0000000 00000010266 14232154237 0024027 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateSnapshotInput struct {
MetaData map[string]string
}
type CreateSnapshotResult struct {
autorest.Response
// This header is a DateTime value that uniquely identifies the share snapshot.
// The value of this header may be used in subsequent requests to access the share snapshot.
// This value is opaque.
SnapshotDateTime string
}
// CreateSnapshot creates a read-only snapshot of the share
// A share can support creation of 200 share snapshots. Attempting to create more than 200 share snapshots fails with 409 (Conflict).
// Attempting to create a share snapshot while a previous Snapshot Share operation is in progress fails with 409 (Conflict).
func (client Client) CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "CreateSnapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreateSnapshotPreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.CreateSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure sending request")
return
}
result, err = client.CreateSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure responding to request")
return
}
return
}
// CreateSnapshotPreparer prepares the CreateSnapshot request.
func (client Client) CreateSnapshotPreparer(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSnapshotSender sends the CreateSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateSnapshotResponder handles the response to the CreateSnapshot request. The method always
// closes the http.Response Body.
func (client Client) CreateSnapshotResponder(resp *http.Response) (result CreateSnapshotResult, err error) {
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/snapshot_delete.go 0000664 0000000 0000000 00000006552 14232154237 0024031 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// DeleteSnapshot deletes the specified Snapshot of a Storage Share
func (client Client) DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` must be a lower-cased string.")
}
if shareSnapshot == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareSnapshot` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, shareName, shareSnapshot)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, shareName string, shareSnapshot string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
"sharesnapshot": autorest.Encode("query", shareSnapshot),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/snapshot_get.go 0000664 0000000 0000000 00000007101 14232154237 0023335 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetSnapshotPropertiesResult struct {
autorest.Response
MetaData map[string]string
}
// GetSnapshot gets information about the specified Snapshot of the specified Storage Share
func (client Client) GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` must be a lower-cased string.")
}
if snapshotShare == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`snapshotShare` cannot be an empty string.")
}
req, err := client.GetSnapshotPreparer(ctx, accountName, shareName, snapshotShare)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.GetSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure sending request")
return
}
result, err = client.GetSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPreparer(ctx context.Context, accountName, shareName, snapshotShare string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"snapshot": autorest.Encode("query", snapshotShare),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSnapshotSender sends the GetSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetSnapshotResponder handles the response to the GetSnapshot request. The method always
// closes the http.Response Body.
func (client Client) GetSnapshotResponder(resp *http.Response) (result GetSnapshotPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/stats.go 0000664 0000000 0000000 00000006470 14232154237 0022005 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetStatsResult struct {
autorest.Response
// The approximate size of the data stored on the share.
// Note that this value may not include all recently created or recently resized files.
ShareUsageBytes int64 `xml:"ShareUsageBytes"`
}
// GetStats returns information about the specified Storage Share
func (client Client) GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` must be a lower-cased string.")
}
req, err := client.GetStatsPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", nil, "Failure preparing request")
return
}
resp, err := client.GetStatsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure sending request")
return
}
result, err = client.GetStatsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure responding to request")
return
}
return
}
// GetStatsPreparer prepares the GetStats request.
func (client Client) GetStatsPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "stats"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetStatsSender sends the GetStats request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetStatsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetStatsResponder handles the response to the GetStats request. The method always
// closes the http.Response Body.
func (client Client) GetStatsResponder(resp *http.Response) (result GetStatsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/file/shares/version.go 0000664 0000000 0000000 00000000464 14232154237 0022331 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/queue/ 0000775 0000000 0000000 00000000000 14232154237 0017231 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/queue/messages/ 0000775 0000000 0000000 00000000000 14232154237 0021040 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/queue/messages/README.md 0000664 0000000 0000000 00000002062 14232154237 0022317 0 ustar 00root root 0000000 0000000 ## Queue Storage Messages SDK for API version 2019-12-12
This package allows you to interact with the Messages Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/queue/messages"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
messagesClient := messages.New()
messagesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := messages.PutInput{
Message: "hello",
}
if _, err := messagesClient.Put(ctx, accountName, queueName, input); err != nil {
return fmt.Errorf("Error creating Message: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/queue/messages/api.go 0000664 0000000 0000000 00000001466 14232154237 0022147 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageQueueMessage interface {
Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error)
Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error)
GetResourceID(accountName, queueName, messageID string) string
Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error)
Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error)
Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/client.go 0000664 0000000 0000000 00000001114 14232154237 0022642 0 ustar 00root root 0000000 0000000 package messages
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Messages.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/delete.go 0000664 0000000 0000000 00000006523 14232154237 0022637 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a specific message
func (client Client) Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Delete", "`queueName` must be a lower-cased string.")
}
if messageID == "" {
return result, validation.NewError("messages.Client", "Delete", "`messageID` cannot be an empty string.")
}
if popReceipt == "" {
return result, validation.NewError("messages.Client", "Delete", "`popReceipt` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName, messageID, popReceipt)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, queueName, messageID, popReceipt string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", popReceipt),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/get.go 0000664 0000000 0000000 00000007666 14232154237 0022165 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
// VisibilityTimeout specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
VisibilityTimeout *int
}
// Get retrieves one or more messages from the front of the queue
func (client Client) Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Get", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Get", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Get", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Get", "`numberOfMessages` must be between 1 and 32.")
}
if input.VisibilityTimeout != nil {
t := *input.VisibilityTimeout
maxTime := (time.Hour * 24 * 7).Seconds()
if t < 1 || t < int(maxTime) {
return result, validation.NewError("messages.Client", "Get", "`input.VisibilityTimeout` must be larger than or equal to 1 second, and cannot be larger than 7 days.")
}
}
req, err := client.GetPreparer(ctx, accountName, queueName, numberOfMessages, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("query", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/lifecycle_test.go 0000664 0000000 0000000 00000005565 14232154237 0024400 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/queue/queues"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageQueueMessage = Client{}
func TestLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := queues.NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
messagesClient := NewWithEnvironment(client.Environment)
messagesClient.Client = client.PrepareWithAuthorizer(messagesClient.Client, storageAuth)
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error creating queue: %s", err)
}
defer queuesClient.Delete(ctx, accountName, queueName)
input := PutInput{
Message: "ohhai",
}
putResp, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message in queue: %s", err)
}
messageId := (*putResp.QueueMessages)[0].MessageId
popReceipt := (*putResp.QueueMessages)[0].PopReceipt
_, err = messagesClient.Update(ctx, accountName, queueName, messageId, UpdateInput{
PopReceipt: popReceipt,
Message: "Updated message",
VisibilityTimeout: 65,
})
if err != nil {
t.Fatalf("Error updating: %s", err)
}
for i := 0; i < 5; i++ {
input := PutInput{
Message: fmt.Sprintf("Message %d", i),
}
_, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message %d in queue: %s", i, err)
}
}
peakedMessages, err := messagesClient.Peek(ctx, accountName, queueName, 3)
if err != nil {
t.Fatalf("Error peaking messages: %s", err)
}
for _, v := range *peakedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
}
retrievedMessages, err := messagesClient.Get(ctx, accountName, queueName, 6, GetInput{})
if err != nil {
t.Fatalf("Error retrieving messages: %s", err)
}
for _, v := range *retrievedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
_, err = messagesClient.Delete(ctx, accountName, queueName, v.MessageId, v.PopReceipt)
if err != nil {
t.Fatalf("Error deleting message from queue: %s", err)
}
}
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/models.go 0000664 0000000 0000000 00000001010 14232154237 0022642 0 ustar 00root root 0000000 0000000 package messages
import "github.com/Azure/go-autorest/autorest"
type QueueMessage struct {
MessageText string `xml:"MessageText"`
}
type QueueMessagesListResult struct {
autorest.Response
QueueMessages *[]QueueMessageResponse `xml:"QueueMessage"`
}
type QueueMessageResponse struct {
MessageId string `xml:"MessageId"`
InsertionTime string `xml:"InsertionTime"`
ExpirationTime string `xml:"ExpirationTime"`
PopReceipt string `xml:"PopReceipt"`
TimeNextVisible string `xml:"TimeNextVisible"`
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/peek.go 0000664 0000000 0000000 00000006512 14232154237 0022317 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Peek retrieves one or more messages from the front of the queue, but doesn't alter the visibility of the messages
func (client Client) Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Peek", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Peek", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Peek", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Peek", "`numberOfMessages` must be between 1 and 32.")
}
req, err := client.PeekPreparer(ctx, accountName, queueName, numberOfMessages)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", nil, "Failure preparing request")
return
}
resp, err := client.PeekSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure sending request")
return
}
result, err = client.PeekResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure responding to request")
return
}
return
}
// PeekPreparer prepares the Peek request.
func (client Client) PeekPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
"peekonly": autorest.Encode("query", true),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PeekSender sends the Peek request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PeekSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PeekResponder handles the response to the Peek request. The method always
// closes the http.Response Body.
func (client Client) PeekResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/put.go 0000664 0000000 0000000 00000010107 14232154237 0022176 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// The maximum time-to-live can be any positive number,
// as well as -1 indicating that the message does not expire.
// If this parameter is omitted, the default time-to-live is 7 days.
MessageTtl *int
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// visibilitytimeout should be set to a value smaller than the time-to-live value.
// If not specified, the default value is 0.
VisibilityTimeout *int
}
// Put adds a new message to the back of the message queue
func (client Client) Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Put", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Put", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Put", "`queueName` must be a lower-cased string.")
}
req, err := client.PutPreparer(ctx, accountName, queueName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", nil, "Failure preparing request")
return
}
resp, err := client.PutSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure sending request")
return
}
result, err = client.PutResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure responding to request")
return
}
return
}
// PutPreparer prepares the Put request.
func (client Client) PutPreparer(ctx context.Context, accountName, queueName string, input PutInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{}
if input.MessageTtl != nil {
queryParameters["messagettl"] = autorest.Encode("path", *input.MessageTtl)
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("path", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutSender sends the Put request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutResponder handles the response to the Put request. The method always
// closes the http.Response Body.
func (client Client) PutResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/resource_id.go 0000664 0000000 0000000 00000003044 14232154237 0023673 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Message within a Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName, messageID string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/messages/%s", domain, queueName, messageID)
}
type ResourceID struct {
AccountName string
QueueName string
MessageID string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Message within a Queue
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) != 3 {
return nil, fmt.Errorf("Expected the path to contain 3 segments but got %d", len(segments))
}
queueName := segments[0]
messageID := segments[2]
return &ResourceID{
AccountName: *accountName,
MessageID: messageID,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/resource_id_test.go 0000664 0000000 0000000 00000004321 14232154237 0024731 0 ustar 00root root 0000000 0000000 package messages
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1", "message1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected Queue Name to be `queue1` but got %q", actual.QueueName)
}
if actual.MessageID != "message1" {
t.Fatalf("Expected Message ID to be `message1` but got %q", actual.MessageID)
}
}
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/update.go 0000664 0000000 0000000 00000010071 14232154237 0022650 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type UpdateInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// Specifies the valid pop receipt value required to modify this message.
PopReceipt string
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// A message can be updated until it has been deleted or has expired.
VisibilityTimeout int
}
// Update updates an existing message based on it's Pop Receipt
func (client Client) Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Update", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Update", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Update", "`queueName` must be a lower-cased string.")
}
if input.PopReceipt == "" {
return result, validation.NewError("messages.Client", "Update", "`input.PopReceipt` cannot be an empty string.")
}
req, err := client.UpdatePreparer(ctx, accountName, queueName, messageID, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", nil, "Failure preparing request")
return
}
resp, err := client.UpdateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure sending request")
return
}
result, err = client.UpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure responding to request")
return
}
return
}
// UpdatePreparer prepares the Update request.
func (client Client) UpdatePreparer(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", input.PopReceipt),
"visibilitytimeout": autorest.Encode("query", input.VisibilityTimeout),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UpdateSender sends the Update request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UpdateResponder handles the response to the Update request. The method always
// closes the http.Response Body.
func (client Client) UpdateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/messages/version.go 0000664 0000000 0000000 00000000466 14232154237 0023062 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/ 0000775 0000000 0000000 00000000000 14232154237 0020540 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/queue/queues/README.md 0000664 0000000 0000000 00000002013 14232154237 0022013 0 ustar 00root root 0000000 0000000 ## Queue Storage Queues SDK for API version 2019-12-12
This package allows you to interact with the Queues Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/queue/queues"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
queuesClient := queues.New()
queuesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := queuesClient.Create(ctx, accountName, queueName, metadata); err != nil {
return fmt.Errorf("Error creating Queue: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/queue/queues/api.go 0000664 0000000 0000000 00000001556 14232154237 0021647 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageQueue interface {
Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error)
SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error)
GetResourceID(accountName, queueName string) string
SetServiceProperties(ctx context.Context, accountName string, properties StorageServiceProperties) (result autorest.Response, err error)
GetServiceProperties(ctx context.Context, accountName string) (result StorageServicePropertiesResponse, err error)
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/client.go 0000664 0000000 0000000 00000001126 14232154237 0022345 0 ustar 00root root 0000000 0000000 package queues
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Queue Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/create.go 0000664 0000000 0000000 00000006247 14232154237 0022343 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates the specified Queue within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Create", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Create", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Create", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/delete.go 0000664 0000000 0000000 00000005502 14232154237 0022333 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Queue within the specified Storage Account
func (client Client) Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Delete", "`queueName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/lifecycle_test.go 0000664 0000000 0000000 00000014166 14232154237 0024075 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageQueue = Client{}
func TestQueuesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
_, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
// first let's test an empty container
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
// then let's retrieve it to ensure there's no metadata..
resp, err := queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// then let's add some..
updatedMetaData := map[string]string{
"band": "panic",
"boots": "the-overpass",
}
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, updatedMetaData)
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error re-retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 2 {
t.Fatalf("Expected metadata to have 2 items but got: %s", resp.MetaData)
}
if resp.MetaData["band"] != "panic" {
t.Fatalf("Expected `band` to be `panic` but got: %s", resp.MetaData["band"])
}
if resp.MetaData["boots"] != "the-overpass" {
t.Fatalf("Expected `boots` to be `the-overpass` but got: %s", resp.MetaData["boots"])
}
// and woo let's remove it again
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// set some properties
props := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "GET,PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
CorsRule{
AllowedMethods: "POST",
AllowedOrigins: "http://www.test.com",
ExposedHeaders: "*",
AllowedHeaders: "x-method-*",
MaxAgeInSeconds: 200,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err := queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) > 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "GET,PUT" {
t.Fatalf("CORS Methods weren't set!")
}
if properties.Cors.CorsRule[1].AllowedMethods != "POST" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
includeAPIS := true
// set some properties
props2 := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
IncludeAPIs: &includeAPIS,
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props2)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err = queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) == 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "PUT" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if !properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
log.Printf("[DEBUG] Deleting..")
_, err = queuesClient.Delete(ctx, accountName, queueName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/metadata_get.go 0000664 0000000 0000000 00000006376 14232154237 0023522 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the metadata for this Queue
func (client Client) GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/metadata_set.go 0000664 0000000 0000000 00000006576 14232154237 0023540 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData returns the metadata for this Queue
func (client Client) SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/models.go 0000664 0000000 0000000 00000002410 14232154237 0022347 0 ustar 00root root 0000000 0000000 package queues
type StorageServiceProperties struct {
Logging *LoggingConfig `xml:"Logging,omitempty"`
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
Cors *Cors `xml:"Cors,omitempty"`
}
type LoggingConfig struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
}
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
// Element IncludeAPIs is only expected when Metrics is enabled
IncludeAPIs *bool `xml:"IncludeAPIs,omitempty"`
}
type RetentionPolicy struct {
Enabled bool `xml:"Enabled"`
Days int `xml:"Days,omitempty"`
}
type Cors struct {
CorsRule []CorsRule `xml:"CorsRule"`
}
type CorsRule struct {
AllowedOrigins string `xml:"AllowedOrigins"`
AllowedMethods string `xml:"AllowedMethods"`
AllowedHeaders string `xml:"AllowedHeaders`
ExposedHeaders string `xml:"ExposedHeaders"`
MaxAgeInSeconds int `xml:"MaxAgeInSeconds"`
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/properties_get.go 0000664 0000000 0000000 00000005670 14232154237 0024132 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type StorageServicePropertiesResponse struct {
StorageServiceProperties
autorest.Response
}
// SetServiceProperties gets the properties for this queue
func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result StorageServicePropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.GetServicePropertiesPreparer(ctx, accountName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.GetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// GetServicePropertiesPreparer prepares the GetServiceProperties request.
func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetServicePropertiesSender sends the GetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetServicePropertiesResponder handles the response to the GetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) GetServicePropertiesResponder(resp *http.Response) (result StorageServicePropertiesResponse, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/properties_set.go 0000664 0000000 0000000 00000005575 14232154237 0024152 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetServiceProperties sets the properties for this queue
func (client Client) SetServiceProperties(ctx context.Context, accountName string, properties StorageServiceProperties) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.SetServicePropertiesPreparer(ctx, accountName, properties)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetServicePropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.SetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// SetServicePropertiesPreparer prepares the SetServiceProperties request.
func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, properties StorageServiceProperties) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(properties),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) SetServicePropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/resource_id.go 0000664 0000000 0000000 00000002315 14232154237 0023373 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, queueName)
}
type ResourceID struct {
AccountName string
QueueName string
}
// ParseResourceID parses the Resource ID and returns an Object which
// can be used to interact with a Queue within a Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.queue.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
queueName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/resource_id_test.go 0000664 0000000 0000000 00000003701 14232154237 0024432 0 ustar 00root root 0000000 0000000 package queues
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected the queue name to be `queue1` but got %q", actual.QueueName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/queue/queues/version.go 0000664 0000000 0000000 00000000464 14232154237 0022560 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/table/ 0000775 0000000 0000000 00000000000 14232154237 0017174 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/table/entities/ 0000775 0000000 0000000 00000000000 14232154237 0021020 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/table/entities/README.md 0000664 0000000 0000000 00000002166 14232154237 0022304 0 ustar 00root root 0000000 0000000 ## Table Storage Entities SDK for API version 2019-12-12
This package allows you to interact with the Entities Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/table/entities"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
entitiesClient := entities.New()
entitiesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := entities.InsertEntityInput{
PartitionKey: "abc",
RowKey: "123",
MetaDataLevel: entities.NoMetaData,
Entity: map[string]interface{}{
"title": "Don't Kill My Vibe",
"artist": "Sigrid",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, input); err != nil {
return fmt.Errorf("Error creating Entity: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/table/entities/api.go 0000664 0000000 0000000 00000001700 14232154237 0022116 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageTableEntity interface {
Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error)
Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error)
InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error)
InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error)
Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error)
Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error)
GetResourceID(accountName, tableName, partitionKey, rowKey string) string
}
giovanni-0.20.0/storage/2019-12-12/table/entities/client.go 0000664 0000000 0000000 00000001130 14232154237 0022620 0 ustar 00root root 0000000 0000000 package entities
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/table/entities/delete.go 0000664 0000000 0000000 00000007327 14232154237 0022622 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteEntityInput struct {
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Delete deletes an existing entity in a table.
func (client Client) Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Delete", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.RowKey` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
// TODO: support for eTags
"If-Match": "*",
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/entities/get.go 0000664 0000000 0000000 00000007013 14232154237 0022127 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetEntityInput struct {
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
}
type GetEntityResult struct {
autorest.Response
Entity map[string]interface{}
}
// Get queries entities in a table and includes the $filter and $select options.
func (client Client) Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Get", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Get", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.RowKey` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, tableName string, input GetEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetEntityResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result.Entity),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/entities/insert.go 0000664 0000000 0000000 00000010207 14232154237 0022653 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertEntityInput struct {
// The level of MetaData provided for this Entity
MetaDataLevel MetaDataLevel
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Insert inserts a new entity into a table.
func (client Client) Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Insert", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Insert", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", nil, "Failure preparing request")
return
}
resp, err := client.InsertSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure sending request")
return
}
result, err = client.InsertResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure responding to request")
return
}
return
}
// InsertPreparer prepares the Insert request.
func (client Client) InsertPreparer(ctx context.Context, accountName, tableName string, input InsertEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"Prefer": "return-no-content",
}
input.Entity["PartitionKey"] = input.PartitionKey
input.Entity["RowKey"] = input.RowKey
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertSender sends the Insert request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertResponder handles the response to the Insert request. The method always
// closes the http.Response Body.
func (client Client) InsertResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/entities/insert_or_merge.go 0000664 0000000 0000000 00000010625 14232154237 0024536 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrMergeEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrMerge updates an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrMergePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrMergeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure sending request")
return
}
result, err = client.InsertOrMergeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure responding to request")
return
}
return
}
// InsertOrMergePreparer prepares the InsertOrMerge request.
func (client Client) InsertOrMergePreparer(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrMergeSender sends the InsertOrMerge request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrMergeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrMergeResponder handles the response to the InsertOrMerge request. The method always
// closes the http.Response Body.
func (client Client) InsertOrMergeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/entities/insert_or_replace.go 0000664 0000000 0000000 00000010706 14232154237 0025052 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrReplaceEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrReplace replaces an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrReplacePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrReplaceSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure sending request")
return
}
result, err = client.InsertOrReplaceResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure responding to request")
return
}
return
}
// InsertOrReplacePreparer prepares the InsertOrReplace request.
func (client Client) InsertOrReplacePreparer(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrReplaceSender sends the InsertOrReplace request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrReplaceSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrReplaceResponder handles the response to the InsertOrReplace request. The method always
// closes the http.Response Body.
func (client Client) InsertOrReplaceResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/entities/lifecycle_test.go 0000664 0000000 0000000 00000010202 14232154237 0024340 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/table/tables"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageTableEntity = Client{}
func TestEntitiesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := tables.NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
defer tablesClient.Delete(ctx, accountName, tableName)
entitiesClient := NewWithEnvironment(client.Environment)
entitiesClient.Client = client.PrepareWithAuthorizer(entitiesClient.Client, storageAuth)
partitionKey := "hello"
rowKey := "there"
t.Logf("[DEBUG] Inserting..")
insertInput := InsertEntityInput{
MetaDataLevel: NoMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "world",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, insertInput); err != nil {
t.Logf("Error retrieving: %s", err)
}
t.Logf("[DEBUG] Insert or Merging..")
insertOrMergeInput := InsertOrMergeEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "ther88e",
},
}
if _, err := entitiesClient.InsertOrMerge(ctx, accountName, tableName, insertOrMergeInput); err != nil {
t.Logf("Error insert/merging: %s", err)
}
t.Logf("[DEBUG] Insert or Replacing..")
insertOrReplaceInput := InsertOrReplaceEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "pandas",
},
}
if _, err := entitiesClient.InsertOrReplace(ctx, accountName, tableName, insertOrReplaceInput); err != nil {
t.Logf("Error inserting/replacing: %s", err)
}
t.Logf("[DEBUG] Querying..")
queryInput := QueryEntitiesInput{
MetaDataLevel: NoMetaData,
}
results, err := entitiesClient.Query(ctx, accountName, tableName, queryInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
if len(results.Entities) != 1 {
t.Fatalf("Expected 1 item but got %d", len(results.Entities))
}
for _, v := range results.Entities {
thisPartitionKey := v["PartitionKey"].(string)
thisRowKey := v["RowKey"].(string)
if partitionKey != thisPartitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, thisPartitionKey)
}
if rowKey != thisRowKey {
t.Fatalf("Expected Partition Key to be %q but got %q", rowKey, thisRowKey)
}
}
t.Logf("[DEBUG] Retrieving..")
getInput := GetEntityInput{
MetaDataLevel: MinimalMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
}
getResults, err := entitiesClient.Get(ctx, accountName, tableName, getInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
partitionKey2 := getResults.Entity["PartitionKey"].(string)
rowKey2 := getResults.Entity["RowKey"].(string)
if partitionKey2 != partitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, partitionKey2)
}
if rowKey2 != rowKey {
t.Fatalf("Expected Row Key to be %q but got %q", rowKey, rowKey2)
}
t.Logf("[DEBUG] Deleting..")
deleteInput := DeleteEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
}
if _, err := entitiesClient.Delete(ctx, accountName, tableName, deleteInput); err != nil {
t.Logf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2019-12-12/table/entities/models.go 0000664 0000000 0000000 00000000306 14232154237 0022631 0 ustar 00root root 0000000 0000000 package entities
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
giovanni-0.20.0/storage/2019-12-12/table/entities/query.go 0000664 0000000 0000000 00000012065 14232154237 0022520 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type QueryEntitiesInput struct {
// An optional OData filter
Filter *string
// An optional comma-separated
PropertyNamesToSelect *[]string
// An optional OData top
Top *int
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
// The Next Partition Key used to load data from a previous point
NextPartitionKey *string
// The Next Row Key used to load data from a previous point
NextRowKey *string
}
type QueryEntitiesResult struct {
autorest.Response
NextPartitionKey string
NextRowKey string
MetaData string `json:"odata.metadata,omitempty"`
Entities []map[string]interface{} `json:"value"`
}
// Query queries entities in a table and includes the $filter and $select options.
func (client Client) Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Query", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Query", "`tableName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"additionalParameters": "",
}
//PartitionKey='',RowKey=''
additionalParams := make([]string, 0)
if input.PartitionKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("PartitionKey='%s'", input.PartitionKey))
}
if input.RowKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("RowKey='%s'", input.RowKey))
}
if len(additionalParams) > 0 {
pathParameters["additionalParameters"] = autorest.Encode("path", strings.Join(additionalParams, ","))
}
queryParameters := map[string]interface{}{}
if input.Filter != nil {
queryParameters["$filter"] = autorest.Encode("query", *input.Filter)
}
if input.PropertyNamesToSelect != nil {
queryParameters["$select"] = autorest.Encode("query", strings.Join(*input.PropertyNamesToSelect, ","))
}
if input.Top != nil {
queryParameters["$top"] = autorest.Encode("query", *input.Top)
}
if input.NextPartitionKey != nil {
queryParameters["NextPartitionKey"] = *input.NextPartitionKey
}
if input.NextRowKey != nil {
queryParameters["NextRowKey"] = *input.NextRowKey
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
// GET /myaccount/Customers()?$filter=(Rating%20ge%203)%20and%20(Rating%20le%206)&$select=PartitionKey,RowKey,Address,CustomerSince
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}({additionalParameters})", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result QueryEntitiesResult, err error) {
if resp != nil && resp.Header != nil {
result.NextPartitionKey = resp.Header.Get("x-ms-continuation-NextPartitionKey")
result.NextRowKey = resp.Header.Get("x-ms-continuation-NextRowKey")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/entities/resource_id.go 0000664 0000000 0000000 00000005370 14232154237 0023657 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Entity
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName, partitionKey, rowKey string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s(PartitionKey='%s',RowKey='%s')", domain, tableName, partitionKey, rowKey)
}
type ResourceID struct {
AccountName string
TableName string
PartitionKey string
RowKey string
}
// ParseResourceID parses the specified Resource ID and returns an object which
// can be used to look up the specified Entity within the specified Table
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.Contains(uri.Path, "(") || !strings.HasSuffix(uri.Path, ")") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `tables(PartitionKey='',RowKey='')` but got %q", path)
}
// NOTE: honestly this could probably be a RegEx, but this seemed like the simplest way to
// allow these two fields to be specified in either order
indexOfBracket := strings.IndexByte(path, '(')
tableName := path[0:indexOfBracket]
// trim off the brackets
temp := strings.TrimPrefix(path, fmt.Sprintf("%s(", tableName))
temp = strings.TrimSuffix(temp, ")")
dictionary := strings.Split(temp, ",")
partitionKey := ""
rowKey := ""
for _, v := range dictionary {
split := strings.Split(v, "=")
if len(split) != 2 {
return nil, fmt.Errorf("Expected 2 segments but got %d for %q", len(split), v)
}
key := split[0]
value := strings.TrimSuffix(strings.TrimPrefix(split[1], "'"), "'")
if strings.EqualFold(key, "PartitionKey") {
partitionKey = value
} else if strings.EqualFold(key, "RowKey") {
rowKey = value
} else {
return nil, fmt.Errorf("Unexpected Key %q", key)
}
}
if partitionKey == "" {
return nil, fmt.Errorf("Expected a PartitionKey but didn't get one")
}
if rowKey == "" {
return nil, fmt.Errorf("Expected a RowKey but didn't get one")
}
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
PartitionKey: partitionKey,
RowKey: rowKey,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/table/entities/resource_id_test.go 0000664 0000000 0000000 00000005012 14232154237 0024707 0 ustar 00root root 0000000 0000000 package entities
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1", "partition1", "row1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
if actual.PartitionKey != "partition1" {
t.Fatalf("Expected Partition Key to be `partition1` but got %q", actual.PartitionKey)
}
if actual.RowKey != "row1" {
t.Fatalf("Expected Row Key to be `row1` but got %q", actual.RowKey)
}
}
}
giovanni-0.20.0/storage/2019-12-12/table/entities/version.go 0000664 0000000 0000000 00000000466 14232154237 0023042 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2019-12-12/table/tables/ 0000775 0000000 0000000 00000000000 14232154237 0020446 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2019-12-12/table/tables/README.md 0000664 0000000 0000000 00000001550 14232154237 0021726 0 ustar 00root root 0000000 0000000 ## Table Storage Tables SDK for API version 2019-12-12
This package allows you to interact with the Tables Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2019-12-12/table/tables"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
tablesClient := tables.New()
tablesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
if _, err := tablesClient.Insert(ctx, accountName, tableName); err != nil {
return fmt.Errorf("Error creating Table: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2019-12-12/table/tables/acl_get.go 0000664 0000000 0000000 00000005654 14232154237 0022405 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL returns the Access Control List for the specified Table
func (client Client) GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`tableName` cannot be an empty string.")
}
req, err := client.GetACLPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/tables/acl_set.go 0000664 0000000 0000000 00000006062 14232154237 0022413 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"encoding/xml"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List for the specified Table
func (client Client) SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`tableName` cannot be an empty string.")
}
req, err := client.SetACLPreparer(ctx, accountName, tableName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/tables/api.go 0000664 0000000 0000000 00000001417 14232154237 0021551 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageTable interface {
Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error)
Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
GetResourceID(accountName, tableName string) string
Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error)
SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2019-12-12/table/tables/client.go 0000664 0000000 0000000 00000001126 14232154237 0022253 0 ustar 00root root 0000000 0000000 package tables
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2019-12-12/table/tables/create.go 0000664 0000000 0000000 00000005571 14232154237 0022250 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type createTableRequest struct {
TableName string `json:"TableName"`
}
// Create creates a new table in the storage account.
func (client Client) Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Create", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Create", "`tableName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// NOTE: we could support returning metadata here, but it doesn't appear to be directly useful
// vs making a request using the Get methods as-necessary?
"Accept": "application/json;odata=nometadata",
"Prefer": "return-no-content",
}
body := createTableRequest{
TableName: tableName,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithJSON(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/tables/delete.go 0000664 0000000 0000000 00000005260 14232154237 0022242 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified table and any data it contains.
func (client Client) Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Delete", "`tableName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/tables/exists.go 0000664 0000000 0000000 00000005304 14232154237 0022316 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Exists checks that the specified table exists
func (client Client) Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Exists", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Exists", "`tableName` cannot be an empty string.")
}
req, err := client.ExistsPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", nil, "Failure preparing request")
return
}
resp, err := client.ExistsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure sending request")
return
}
result, err = client.ExistsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure responding to request")
return
}
return
}
// ExistsPreparer prepares the Exists request.
func (client Client) ExistsPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.AsContentType("application/xml"),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ExistsSender sends the Exists request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ExistsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ExistsResponder handles the response to the Exists request. The method always
// closes the http.Response Body.
func (client Client) ExistsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/tables/lifecycle_test.go 0000664 0000000 0000000 00000007234 14232154237 0024001 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageTable = Client{}
func TestTablesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
// first look it up directly and confirm it's there
t.Logf("[DEBUG] Checking if Table exists..")
if _, err := tablesClient.Exists(ctx, accountName, tableName); err != nil {
t.Fatalf("Error checking if Table %q exists: %s", tableName, err)
}
// then confirm it exists in the Query too
t.Logf("[DEBUG] Querying for Tables..")
result, err := tablesClient.Query(ctx, accountName, NoMetaData)
if err != nil {
t.Fatalf("Error retrieving Tables: %s", err)
}
found := false
for _, v := range result.Tables {
log.Printf("[DEBUG] Table: %q", v.TableName)
if v.TableName == tableName {
found = true
}
}
if !found {
t.Fatalf("%q was not found in the Query response!", tableName)
}
t.Logf("[DEBUG] Setting ACL's for Table %q..", tableName)
acls := []SignedIdentifier{
{
Id: "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=",
AccessPolicy: AccessPolicy{
Permission: "raud",
Start: "2020-11-26T08:49:37.0000000Z",
Expiry: "2020-11-27T08:49:37.0000000Z",
},
},
}
if _, err := tablesClient.SetACL(ctx, accountName, tableName, acls); err != nil {
t.Fatalf("Error setting ACLs: %s", err)
}
t.Logf("[DEBUG] Retrieving ACL's for Table %q..", tableName)
retrievedACLs, err := tablesClient.GetACL(ctx, accountName, tableName)
if err != nil {
t.Fatalf("Error retrieving ACLs: %s", err)
}
if len(retrievedACLs.SignedIdentifiers) != len(acls) {
t.Fatalf("Expected %d but got %q ACLs", len(retrievedACLs.SignedIdentifiers), len(acls))
}
for i, retrievedAcl := range retrievedACLs.SignedIdentifiers {
expectedAcl := acls[i]
if retrievedAcl.Id != expectedAcl.Id {
t.Fatalf("Expected ID to be %q but got %q", retrievedAcl.Id, expectedAcl.Id)
}
if retrievedAcl.AccessPolicy.Start != expectedAcl.AccessPolicy.Start {
t.Fatalf("Expected Start to be %q but got %q", retrievedAcl.AccessPolicy.Start, expectedAcl.AccessPolicy.Start)
}
if retrievedAcl.AccessPolicy.Expiry != expectedAcl.AccessPolicy.Expiry {
t.Fatalf("Expected Expiry to be %q but got %q", retrievedAcl.AccessPolicy.Expiry, expectedAcl.AccessPolicy.Expiry)
}
if retrievedAcl.AccessPolicy.Permission != expectedAcl.AccessPolicy.Permission {
t.Fatalf("Expected Permission to be %q but got %q", retrievedAcl.AccessPolicy.Permission, expectedAcl.AccessPolicy.Permission)
}
}
t.Logf("[DEBUG] Deleting Table %q..", tableName)
if _, err := tablesClient.Delete(ctx, accountName, tableName); err != nil {
t.Fatalf("Error deleting %q: %s", tableName, err)
}
}
giovanni-0.20.0/storage/2019-12-12/table/tables/models.go 0000664 0000000 0000000 00000001324 14232154237 0022260 0 ustar 00root root 0000000 0000000 package tables
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
type GetResultItem struct {
TableName string `json:"TableName"`
// Optional, depending on the MetaData Level
ODataType string `json:"odata.type,omitempty"`
ODataID string `json:"odata.id,omitEmpty"`
ODataEditLink string `json:"odata.editLink,omitEmpty"`
}
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2019-12-12/table/tables/query.go 0000664 0000000 0000000 00000005430 14232154237 0022144 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetResult struct {
autorest.Response
MetaData string `json:"odata.metadata,omitempty"`
Tables []GetResultItem `json:"value"`
}
// Query returns a list of tables under the specified account.
func (client Client) Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Query", "`accountName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, metaDataLevel)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (*http.Request, error) {
// NOTE: whilst this supports ContinuationTokens and 'Top'
// it appears that 'Skip' returns a '501 Not Implemented'
// as such, we intentionally don't support those right now
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", metaDataLevel),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result GetResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2019-12-12/table/tables/resource_id.go 0000664 0000000 0000000 00000003112 14232154237 0023275 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Table
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/Tables('%s')", domain, tableName)
}
type ResourceID struct {
AccountName string
TableName string
}
// ParseResourceID parses the Resource ID and returns an object which
// can be used to interact with the Table within the specified Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.table.core.windows.net/Table('foo')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.HasPrefix(path, "Tables('") || !strings.HasSuffix(path, "')") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `Tables('name')` but got %q", path)
}
// strip off the `Table('')`
tableName := strings.TrimPrefix(uri.Path, "/Tables('")
tableName = strings.TrimSuffix(tableName, "')")
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
}, nil
}
giovanni-0.20.0/storage/2019-12-12/table/tables/resource_id_test.go 0000664 0000000 0000000 00000004010 14232154237 0024332 0 ustar 00root root 0000000 0000000 package tables
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
}
}
giovanni-0.20.0/storage/2019-12-12/table/tables/version.go 0000664 0000000 0000000 00000000464 14232154237 0022466 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2019-12-12"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/ 0000775 0000000 0000000 00000000000 14232154237 0016103 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/README.md 0000664 0000000 0000000 00000001215 14232154237 0017361 0 ustar 00root root 0000000 0000000 # Storage API Version 2020-08-04
The following API's are supported by this SDK - more information about each SDK can be found within the README in each package.
## Blob Storage
- [Blobs API](blob/blobs)
- [Containers API](blob/containers)
- [Accounts API](blob/accounts)
## DataLakeStore Gen2
- [FileSystems API](datalakestore/filesystems)
- [Paths API](datalakestore/paths)
## File Storage
- [Directories API](file/directories)
- [Files API](file/files)
- [Shares API](file/shares)
## Queue Storage
- [Queues API](queue/queues)
- [Messages API](queue/messages)
## Table Storage
- [Entities API](table/entities)
- [Tables API](table/tables)
giovanni-0.20.0/storage/2020-08-04/blob/ 0000775 0000000 0000000 00000000000 14232154237 0017021 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/blob/accounts/ 0000775 0000000 0000000 00000000000 14232154237 0020640 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/blob/accounts/README.md 0000664 0000000 0000000 00000002463 14232154237 0022124 0 ustar 00root root 0000000 0000000 ## Blob Storage Account SDK for API version 2020-08-04
This package allows you to interact with the Accounts Blob Storage API
### Supported Authorizers
* Azure Active Directory
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/accounts"
)
func Example() error {
accountName := "storageaccount1"
// e.g. https://github.com/tombuildsstuff/giovanni/blob/76f5f686c99ecdcc3fa533a0330d0e1aacb1c327/example/azuread-auth/main.go#L54
client, err := buildClient()
if err != nil {
return fmt.Errorf("error building client: %s", err)
}
ctx := context.TODO()
input := StorageServiceProperties{
StaticWebsite: &StaticWebsite{
Enabled: true,
IndexDocument: index,
ErrorDocument404Path: errorDocument,
},
}
_, err = client.SetServiceProperties(ctx, accountName, input)
if err != nil {
return fmt.Errorf("error setting properties: %s", err)
}
time.Sleep(2 * time.Second)
_, err = accountsClient.GetServiceProperties(ctx, accountName)
if err != nil {
return fmt.Errorf("error getting properties: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/blob/accounts/client.go 0000664 0000000 0000000 00000001122 14232154237 0022441 0 ustar 00root root 0000000 0000000 package accounts
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/blob/accounts/get_service_properties.go 0000664 0000000 0000000 00000005205 14232154237 0025744 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetServicePropertiesResult struct {
autorest.Response
ContentType string
StorageServiceProperties *StorageServiceProperties
}
// GetServicePropertiesPreparer prepares the GetServiceProperties request.
func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) {
queryParameters := map[string]interface{}{
"restype": "service",
"comp": "properties",
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
func (client Client) GetServicePropertiesResponder(resp *http.Response) (result GetServicePropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result.StorageServiceProperties),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result GetServicePropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("accounts.Client", "GetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.GetServicePropertiesPreparer(ctx, accountName)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.GetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure responding to request")
return
}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/accounts/models.go 0000664 0000000 0000000 00000011115 14232154237 0022451 0 ustar 00root root 0000000 0000000 package accounts
import "github.com/Azure/go-autorest/autorest"
type SetServicePropertiesResult struct {
autorest.Response
}
type StorageServiceProperties struct {
// Cors - Specifies CORS rules for the Blob service. You can include up to five CorsRule elements in the request. If no CorsRule elements are included in the request body, all CORS rules will be deleted, and CORS will be disabled for the Blob service.
Cors *CorsRules `xml:"Cors,omitempty"`
// DefaultServiceVersion - DefaultServiceVersion indicates the default version to use for requests to the Blob service if an incoming request’s version is not specified. Possible values include version 2008-10-27 and all more recent versions.
DefaultServiceVersion *string `xml:"DefaultServiceVersion,omitempty"`
// DeleteRetentionPolicy - The blob service properties for soft delete.
DeleteRetentionPolicy *DeleteRetentionPolicy `xml:"DeleteRetentionPolicy,omitempty"`
// Logging - The blob service properties for logging access
Logging *Logging `xml:"Logging,omitempty"`
// HourMetrics - The blob service properties for hour metrics
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
// HourMetrics - The blob service properties for minute metrics
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
// StaticWebsite - Optional
StaticWebsite *StaticWebsite `xml:"StaticWebsite,omitempty"`
}
// StaticWebsite sets the static website support properties on the Blob service.
type StaticWebsite struct {
// Enabled - Required. Indicates whether static website support is enabled for the given account.
Enabled bool `xml:"Enabled"`
// IndexDocument - Optional. The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive.
IndexDocument string `xml:"IndexDocument,omitempty"`
// ErrorDocument404Path - Optional. The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive.
ErrorDocument404Path string `xml:"ErrorDocument404Path,omitempty"`
}
// CorsRules sets the CORS rules. You can include up to five CorsRule elements in the request.
type CorsRules struct {
// CorsRules - The List of CORS rules. You can include up to five CorsRule elements in the request.
CorsRules []CorsRule `xml:"CorsRules,omitempty"`
}
// DeleteRetentionPolicy the blob service properties for soft delete.
type DeleteRetentionPolicy struct {
// Enabled - Indicates whether DeleteRetentionPolicy is enabled for the Blob service.
Enabled bool `xml:"Enabled,omitempty"`
// Days - Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365.
Days int32 `xml:"Days,omitempty"`
}
// CorsRule specifies a CORS rule for the Blob service.
type CorsRule struct {
// AllowedOrigins - Required if CorsRule element is present. A list of origin domains that will be allowed via CORS, or "" to allow all domains
AllowedOrigins []string `xml:"AllowedOrigins,omitempty"`
// AllowedMethods - Required if CorsRule element is present. A list of HTTP methods that are allowed to be executed by the origin.
AllowedMethods []string `xml:"AllowedMethods,omitempty"`
// MaxAgeInSeconds - Required if CorsRule element is present. The number of seconds that the client/browser should cache a preflight response.
MaxAgeInSeconds int32 `xml:"MaxAgeInSeconds,omitempty"`
// ExposedHeaders - Required if CorsRule element is present. A list of response headers to expose to CORS clients.
ExposedHeaders []string `xml:"ExposedHeaders,omitempty"`
// AllowedHeaders - Required if CorsRule element is present. A list of headers allowed to be part of the cross-origin request.
AllowedHeaders []string `xml:"AllowedHeaders,omitempty"`
}
// Logging specifies the access logging options for the Blob service.
type Logging struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy DeleteRetentionPolicy `xml:"RetentionPolicy"`
}
// MetricsConfig specifies the hour and/or minute metrics options for the Blob service.
// Elements are all expected
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy DeleteRetentionPolicy `xml:"RetentionPolicy"`
IncludeAPIs bool `xml:"IncludeAPIs"`
}
giovanni-0.20.0/storage/2020-08-04/blob/accounts/set_service_properties.go 0000664 0000000 0000000 00000005322 14232154237 0025760 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetServicePropertiesPreparer prepares the SetServiceProperties request.
func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, input StorageServiceProperties) (*http.Request, error) {
queryParameters := map[string]interface{}{
"restype": "service",
"comp": "properties",
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithHeaders(headers),
autorest.WithXML(input),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) SetServicePropertiesResponder(resp *http.Response) (result SetServicePropertiesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
func (client Client) SetServiceProperties(ctx context.Context, accountName string, input StorageServiceProperties) (result SetServicePropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("accounts.Client", "SetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.SetServicePropertiesPreparer(ctx, accountName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.SetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure responding to request")
return
}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/accounts/set_service_properties_test.go 0000664 0000000 0000000 00000005316 14232154237 0027022 0 ustar 00root root 0000000 0000000 package accounts
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
_, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
accountsClient := NewWithEnvironment(client.Environment)
accountsClient.Client = client.PrepareWithStorageResourceManagerAuth(accountsClient.Client)
input := StorageServiceProperties{}
_, err = accountsClient.SetServiceProperties(ctx, accountName, input)
if err != nil {
t.Fatal(fmt.Errorf("error setting properties: %s", err))
}
var index = "index.html"
//var enabled = true
var errorDocument = "404.html"
input = StorageServiceProperties{
StaticWebsite: &StaticWebsite{
Enabled: true,
IndexDocument: index,
ErrorDocument404Path: errorDocument,
},
Logging: &Logging{
Version: "2.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: DeleteRetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = accountsClient.SetServiceProperties(ctx, accountName, input)
if err != nil {
t.Fatal(fmt.Errorf("error setting properties: %s", err))
}
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
result, err := accountsClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatal(fmt.Errorf("error getting properties: %s", err))
}
website := result.StorageServiceProperties.StaticWebsite
if website.Enabled != true {
t.Fatalf("Expected the StaticWebsite %t but got %t", true, website.Enabled)
}
logging := result.StorageServiceProperties.Logging
if logging.Version != "2.0" {
t.Fatalf("Expected the Logging Version %s but got %s", "2.0", logging.Version)
}
if !logging.Read {
t.Fatalf("Expected the Logging Read %t but got %t", true, logging.Read)
}
if !logging.Write {
t.Fatalf("Expected the Logging Write %t but got %t", true, logging.Write)
}
if !logging.Delete {
t.Fatalf("Expected the Logging Delete %t but got %t", true, logging.Delete)
}
if !logging.RetentionPolicy.Enabled {
t.Fatalf("Expected the Logging RetentionPolicy.Enabled %t but got %t", true, logging.RetentionPolicy.Enabled)
}
if logging.RetentionPolicy.Days != 7 {
t.Fatalf("Expected the Logging RetentionPolicy.Enabled %d but got %d", 7, logging.RetentionPolicy.Days)
}
}
giovanni-0.20.0/storage/2020-08-04/blob/accounts/version.go 0000664 0000000 0000000 00000000466 14232154237 0022662 0 ustar 00root root 0000000 0000000 package accounts
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/ 0000775 0000000 0000000 00000000000 14232154237 0020122 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/blob/blobs/README.md 0000664 0000000 0000000 00000002263 14232154237 0021404 0 ustar 00root root 0000000 0000000 ## Blob Storage Blobs SDK for API version 2020-08-04
This package allows you to interact with the Blobs Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/blobs"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
fileName := "example-large-file.iso"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
blobClient := blobs.New()
blobClient.Client.Authorizer = storageAuth
ctx := context.TODO()
copyInput := blobs.CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/blob/blobs/api.go 0000664 0000000 0000000 00000011051 14232154237 0021220 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
)
type StorageBlob interface {
AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error)
Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error)
AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error)
CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error
Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error)
DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error)
DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error)
Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error)
GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error)
GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error)
IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error)
AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error)
BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error)
ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error)
ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error)
RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error)
SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error)
GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error)
SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error)
PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error)
PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error)
PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error)
PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error
PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error)
PutBlockFromURL(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (result PutBlockFromURLResult, err error)
PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error)
PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error)
PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error)
GetResourceID(accountName, containerName, blobName string) string
SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error)
Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error)
GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error)
Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/append_block.go 0000664 0000000 0000000 00000014462 14232154237 0023101 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AppendBlockInput struct {
// 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 an AppendPositionConditionNotMet
// error (HTTP status code 412 – Precondition Failed)
BlobConditionAppendPosition *int64
// 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
// an MaxBlobSizeConditionNotMet error (HTTP status code 412 – Precondition Failed).
BlobConditionMaxSize *int64
// The Bytes which should be appended to the end of this Append Blob.
// This can either be nil, which creates an empty blob, or a byte array
Content *[]byte
// An MD5 hash of the block content.
// This hash is used to verify the integrity of the block during transport.
// When this header is specified, the storage service compares the hash of the content
// that has arrived with this header value.
//
// Note that this MD5 hash is not stored with the blob.
// If the two hashes do not match, the operation will fail with error code 400 (Bad Request).
ContentMD5 *string
// Required if the blob has an active lease.
// To perform this operation on a blob with an active lease, specify the valid lease ID for this header.
LeaseID *string
}
type AppendBlockResult struct {
autorest.Response
BlobAppendOffset string
BlobCommittedBlockCount int64
ContentMD5 string
ETag string
LastModified string
}
// AppendBlock commits a new block of data to the end of an existing append blob.
func (client Client) AppendBlock(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (result AppendBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AppendBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AppendBlock", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) > (4*1024*1024) {
return result, validation.NewError("files.Client", "PutByteRange", "`input.Content` must be at most 4MB.")
}
req, err := client.AppendBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", nil, "Failure preparing request")
return
}
resp, err := client.AppendBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure sending request")
return
}
result, err = client.AppendBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AppendBlock", resp, "Failure responding to request")
return
}
return
}
// AppendBlockPreparer prepares the AppendBlock request.
func (client Client) AppendBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input AppendBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "appendblock"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.BlobConditionAppendPosition != nil {
headers["x-ms-blob-condition-appendpos"] = *input.BlobConditionAppendPosition
}
if input.BlobConditionMaxSize != nil {
headers["x-ms-blob-condition-maxsize"] = *input.BlobConditionMaxSize
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AppendBlockSender sends the AppendBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AppendBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AppendBlockResponder handles the response to the AppendBlock request. The method always
// closes the http.Response Body.
func (client Client) AppendBlockResponder(resp *http.Response) (result AppendBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobAppendOffset = resp.Header.Get("x-ms-blob-append-offset")
result.ContentMD5 = resp.Header.Get("ETag")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
if v := resp.Header.Get("x-ms-blob-committed-block-count"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
result.BlobCommittedBlockCount = int64(i)
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/blob_append_test.go 0000664 0000000 0000000 00000011330 14232154237 0023753 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestAppendBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Append Blob..")
if _, err := blobClient.PutAppendBlob(ctx, accountName, containerName, fileName, PutAppendBlobInput{}); err != nil {
t.Fatalf("Error putting append blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 0 {
t.Fatalf("Expected Content-Length to be 0 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending First Block..")
appendInput := AppendBlockInput{
Content: &[]byte{
12,
48,
93,
76,
29,
10,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending first block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 6 {
t.Fatalf("Expected Content-Length to be 6 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Appending Second Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
92,
62,
64,
47,
83,
77,
},
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Second block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 12 {
t.Fatalf("Expected Content-Length to be 12 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Acquiring Lease..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error acquiring Lease: %s", err)
}
t.Logf("[DEBUG] Lease ID is %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Appending Third Block..")
appendInput = AppendBlockInput{
Content: &[]byte{
64,
35,
28,
93,
11,
23,
},
LeaseID: &leaseDetails.LeaseID,
}
if _, err := blobClient.AppendBlock(ctx, accountName, containerName, fileName, appendInput); err != nil {
t.Fatalf("Error appending Third block: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving Properties..")
props, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != 18 {
t.Fatalf("Expected Content-Length to be 18 but it was %d", props.ContentLength)
}
t.Logf("[DEBUG] Breaking Lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseDetails.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
t.Logf("[DEBUG] Deleting Lease..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/blob_page_test.go 0000664 0000000 0000000 00000005541 14232154237 0023427 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPageBlobLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "append-blob.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Putting Page Blob..")
fileSize := int64(10240000)
if _, err := blobClient.PutPageBlob(ctx, accountName, containerName, fileName, PutPageBlobInput{
BlobContentLengthBytes: fileSize,
}); err != nil {
t.Fatalf("Error putting page blob: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
if props.ContentLength != fileSize {
t.Fatalf("Expected Content-Length to be %d but it was %d", fileSize, props.ContentLength)
}
for iteration := 1; iteration <= 3; iteration++ {
t.Logf("[DEBUG] Putting Page %d of 3..", iteration)
byteArray := func() []byte {
o := make([]byte, 0)
for i := 0; i < 512; i++ {
o = append(o, byte(i))
}
return o
}()
startByte := int64(512 * iteration)
endByte := int64(startByte + 511)
putPageInput := PutPageUpdateInput{
StartByte: startByte,
EndByte: endByte,
Content: byteArray,
}
if _, err := blobClient.PutPageUpdate(ctx, accountName, containerName, fileName, putPageInput); err != nil {
t.Fatalf("Error putting page: %s", err)
}
}
t.Logf("[DEBUG] Deleting..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/client.go 0000664 0000000 0000000 00000001117 14232154237 0021727 0 ustar 00root root 0000000 0000000 package blobs
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Blobs.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/copy.go 0000664 0000000 0000000 00000022706 14232154237 0021432 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the name of the source blob or file.
// Beginning with version 2012-02-12, this value may be a URL of up to 2 KB in length that specifies a blob.
// The value should be URL-encoded as it would appear in a request URI.
// A source blob in the same storage account can be authenticated via Shared Key.
// However, if the source is a blob in another account,
// the source blob must either be public or must be authenticated via a shared access signature.
// If the source blob is public, no authentication is required to perform the copy operation.
//
// Beginning with version 2015-02-21, the source object may be a file in the Azure File service.
// If the source object is a file that is to be copied to a blob, then the source file must be authenticated
// using a shared access signature, whether it resides in the same account or in a different account.
//
// Only storage accounts created on or after June 7th, 2012 allow the Copy Blob operation to
// copy from another storage account.
CopySource string
// The ID of the Lease
// Required if the destination blob has an active lease.
// The lease ID specified for this header must match the lease ID of the destination blob.
// If the request does not include the lease ID or it is not valid,
// the operation fails with status code 412 (Precondition Failed).
//
// If this header is specified and the destination blob does not currently have an active lease,
// the operation will also fail with status code 412 (Precondition Failed).
LeaseID *string
// The ID of the Lease on the Source Blob
// Specify to perform the Copy Blob operation only if the lease ID matches the active lease ID of the source blob.
SourceLeaseID *string
// For page blobs on a premium account only. Specifies the tier to be set on the target blob
AccessTier *AccessTier
// 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.
MetaData map[string]string
// An ETag value.
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value matches the ETag value for an existing destination blob.
// If the ETag for the destination blob does not match the ETag specified for If-Match,
// the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value, or the wildcard character (*).
// Specify an ETag value for this conditional header to copy the blob only if the specified
// ETag value does not match the ETag value for the destination blob.
// Specify the wildcard character (*) to perform the operation only if the destination blob does not exist.
// If the specified condition isn't met, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has been modified since the specified date/time.
// If the destination blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the destination blob
// has not been modified since the specified date/time.
// If the destination blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value.
// Specify this conditional header to copy the source blob only if its ETag matches the value specified.
// If the ETag values do not match, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfMatch *string
// An ETag value.
// Specify this conditional header to copy the blob only if its ETag does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfNoneMatch *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has been modified
// since the specified date/time.
// If the source blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
// This cannot be specified if the source is an Azure File.
SourceIfModifiedSince *string
// A DateTime value.
// Specify this conditional header to copy the blob only if the source blob has not been modified
// since the specified date/time.
// If the source blob has been modified, the Blob service returns status code 412 (Precondition Failed).
// This header cannot be specified if the source is an Azure File.
SourceIfUnmodifiedSince *string
}
type CopyResult struct {
autorest.Response
CopyID string
CopyStatus string
}
// Copy copies a blob to a destination within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Copy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Copy", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
req, err := client.CopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, containerName, blobName string, input CopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": autorest.Encode("header", input.CopySource),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SourceLeaseID != nil {
headers["x-ms-source-lease-id"] = *input.SourceLeaseID
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.SourceIfMatch != nil {
headers["x-ms-source-if-match"] = *input.SourceIfMatch
}
if input.SourceIfNoneMatch != nil {
headers["x-ms-source-if-none-match"] = *input.SourceIfNoneMatch
}
if input.SourceIfModifiedSince != nil {
headers["x-ms-source-if-modified-since"] = *input.SourceIfModifiedSince
}
if input.SourceIfUnmodifiedSince != nil {
headers["x-ms-source-if-unmodified-since"] = *input.SourceIfUnmodifiedSince
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/copy_abort.go 0000664 0000000 0000000 00000007451 14232154237 0022621 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AbortCopyInput struct {
// The Copy ID which should be aborted
CopyID string
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// AbortCopy aborts a pending Copy Blob operation, and leaves a destination blob with zero length and full metadata.
func (client Client) AbortCopy(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AbortCopy", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`blobName` cannot be an empty string.")
}
if input.CopyID == "" {
return result, validation.NewError("blobs.Client", "AbortCopy", "`input.CopyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, containerName, blobName string, input AbortCopyInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", input.CopyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/copy_and_wait.go 0000664 0000000 0000000 00000002050 14232154237 0023266 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"time"
)
// CopyAndWait copies a blob to a destination within the storage account and waits for it to finish copying.
func (client Client) CopyAndWait(ctx context.Context, accountName, containerName, blobName string, input CopyInput, pollingInterval time.Duration) error {
if _, err := client.Copy(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error copying: %s", err)
}
for true {
getInput := GetPropertiesInput{
LeaseID: input.LeaseID,
}
getResult, err := client.GetProperties(ctx, accountName, containerName, blobName, getInput)
if err != nil {
return fmt.Errorf("")
}
switch getResult.CopyStatus {
case Aborted:
return fmt.Errorf("Copy was aborted: %s", getResult.CopyStatusDescription)
case Failed:
return fmt.Errorf("Copy failed: %s", getResult.CopyStatusDescription)
case Success:
return nil
case Pending:
time.Sleep(pollingInterval)
continue
}
}
return fmt.Errorf("Unexpected error waiting for the copy to complete")
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/copy_test.go 0000664 0000000 0000000 00000012644 14232154237 0022471 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCopyFromExistingFile(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
copiedFileName := "copied.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Duplicating that file..")
copiedInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetBlobEndpoint(blobClient.BaseURI, accountName), containerName, fileName),
}
if err := blobClient.CopyAndWait(ctx, accountName, containerName, copiedFileName, copiedInput, refreshInterval); err != nil {
t.Fatalf("Error duplicating file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Original File..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the original file: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Copied File..")
copiedProps, err := blobClient.GetProperties(ctx, accountName, containerName, copiedFileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties for the copied file: %s", err)
}
if props.ContentLength != copiedProps.ContentLength {
t.Fatalf("Expected the content length to be %d but it was %d", props.ContentLength, copiedProps.ContentLength)
}
t.Logf("[DEBUG] Deleting copied file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, copiedFileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
t.Logf("[DEBUG] Deleting original file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
func TestCopyFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties..")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
if props.ContentLength == 0 {
t.Fatalf("Expected the file to be there but looks like it isn't: %d", props.ContentLength)
}
t.Logf("[DEBUG] Deleting file..")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting file: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/delete.go 0000664 0000000 0000000 00000007057 14232154237 0021724 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteInput struct {
// Should any Snapshots for this Blob also be deleted?
// If the Blob has Snapshots and this is set to False a 409 Conflict will be returned
DeleteSnapshots bool
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// Delete marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Delete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Delete", "`blobName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.DeleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/delete_snapshot.go 0000664 0000000 0000000 00000007675 14232154237 0023651 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The DateTime of the Snapshot which should be marked for Deletion
SnapshotDateTime string
}
// DeleteSnapshot marks a single Snapshot of a Blob for Deletion based on it's DateTime, which will be deleted during the next Garbage Collection cycle.
func (client Client) DeleteSnapshot(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`blobName` cannot be an empty string.")
}
if input.SnapshotDateTime == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshot", "`input.SnapshotDateTime` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotDateTime),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/delete_snapshots.go 0000664 0000000 0000000 00000007161 14232154237 0024022 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteSnapshotsInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
// DeleteSnapshots marks all Snapshots of a Blob for Deletion, which will be deleted during the next Garbage Collection Cycle.
func (client Client) DeleteSnapshots(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "DeleteSnapshots", "`blobName` cannot be an empty string.")
}
req, err := client.DeleteSnapshotsPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "DeleteSnapshots", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotsPreparer prepares the DeleteSnapshots request.
func (client Client) DeleteSnapshotsPreparer(ctx context.Context, accountName, containerName, blobName string, input DeleteSnapshotsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// only delete the snapshots but leave the blob as-is
"x-ms-delete-snapshots": "only",
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotsSender sends the DeleteSnapshots request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotsResponder handles the response to the DeleteSnapshots request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/get.go 0000664 0000000 0000000 00000007611 14232154237 0021235 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetResult struct {
autorest.Response
Contents []byte
}
// Get reads or downloads a blob from the system, including its metadata and properties.
func (client Client) Get(ctx context.Context, accountName, containerName, blobName string, input GetInput) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Get", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Get", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Get", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Get", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "Get", "`input.LeaseID` should either be specified or nil, not an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "Get", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, containerName, blobName string, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && int(resp.ContentLength) > 0 {
result.Contents = make([]byte, resp.ContentLength)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/get_block_list.go 0000664 0000000 0000000 00000010765 14232154237 0023446 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetBlockListInput struct {
BlockListType BlockListType
LeaseID *string
}
type GetBlockListResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
// A list of blocks which have been committed
CommittedBlocks CommittedBlocks `xml:"CommittedBlocks,omitempty"`
// A list of blocks which have not yet been committed
UncommittedBlocks UncommittedBlocks `xml:"UncommittedBlocks,omitempty"`
}
// GetBlockList retrieves the list of blocks that have been uploaded as part of a block blob.
func (client Client) GetBlockList(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (result GetBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.GetBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", nil, "Failure preparing request")
return
}
resp, err := client.GetBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure sending request")
return
}
result, err = client.GetBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetBlockList", resp, "Failure responding to request")
return
}
return
}
// GetBlockListPreparer prepares the GetBlockList request.
func (client Client) GetBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input GetBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"blocklisttype": autorest.Encode("query", string(input.BlockListType)),
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetBlockListSender sends the GetBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetBlockListResponder handles the response to the GetBlockList request. The method always
// closes the http.Response Body.
func (client Client) GetBlockListResponder(resp *http.Response) (result GetBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/get_page_ranges.go 0000664 0000000 0000000 00000011500 14232154237 0023560 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPageRangesInput struct {
LeaseID *string
StartByte *int64
EndByte *int64
}
type GetPageRangesResult struct {
autorest.Response
// The size of the blob in bytes
ContentLength *int64
// The Content Type of the blob
ContentType string
// The ETag associated with this blob
ETag string
PageRanges []PageRange `xml:"PageRange"`
}
type PageRange struct {
// The start byte offset for this range, inclusive
Start int64 `xml:"Start"`
// The end byte offset for this range, inclusive
End int64 `xml:"End"`
}
// GetPageRanges returns the list of valid page ranges for a page blob or snapshot of a page blob.
func (client Client) GetPageRanges(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (result GetPageRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`blobName` cannot be an empty string.")
}
if (input.StartByte != nil && input.EndByte == nil) || input.StartByte == nil && input.EndByte != nil {
return result, validation.NewError("blobs.Client", "GetPageRanges", "`input.StartByte` and `input.EndByte` must both be specified, or both be nil.")
}
req, err := client.GetPageRangesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", nil, "Failure preparing request")
return
}
resp, err := client.GetPageRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure sending request")
return
}
result, err = client.GetPageRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetPageRanges", resp, "Failure responding to request")
return
}
return
}
// GetPageRangesPreparer prepares the GetPageRanges request.
func (client Client) GetPageRangesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPageRangesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "pagelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.StartByte != nil && input.EndByte != nil {
headers["x-ms-range"] = fmt.Sprintf("bytes=%d-%d", *input.StartByte, *input.EndByte)
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPageRangesSender sends the GetPageRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPageRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPageRangesResponder handles the response to the GetPageRanges request. The method always
// closes the http.Response Body.
func (client Client) GetPageRangesResponder(resp *http.Response) (result GetPageRangesResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentType = resp.Header.Get("Content-Type")
result.ETag = resp.Header.Get("ETag")
if v := resp.Header.Get("x-ms-blob-content-length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
return
}
i64 := int64(i)
result.ContentLength = &i64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/incremental_copy_blob.go 0000664 0000000 0000000 00000010703 14232154237 0025003 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type IncrementalCopyBlobInput struct {
CopySource string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
}
// IncrementalCopyBlob 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.
func (client Client) IncrementalCopyBlob(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`blobName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "IncrementalCopyBlob", "`input.CopySource` cannot be an empty string.")
}
req, err := client.IncrementalCopyBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", nil, "Failure preparing request")
return
}
resp, err := client.IncrementalCopyBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure sending request")
return
}
result, err = client.IncrementalCopyBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "IncrementalCopyBlob", resp, "Failure responding to request")
return
}
return
}
// IncrementalCopyBlobPreparer prepares the IncrementalCopyBlob request.
func (client Client) IncrementalCopyBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input IncrementalCopyBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "incrementalcopy"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// IncrementalCopyBlobSender sends the IncrementalCopyBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) IncrementalCopyBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// IncrementalCopyBlobResponder handles the response to the IncrementalCopyBlob request. The method always
// closes the http.Response Body.
func (client Client) IncrementalCopyBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/lease_acquire.go 0000664 0000000 0000000 00000011503 14232154237 0023253 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput struct {
// The ID of the existing Lease, if leased
LeaseID *string
// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires.
// A non-infinite lease can be between 15 and 60 seconds
LeaseDuration int
// The Proposed new ID for the Lease
ProposedLeaseID *string
}
type AcquireLeaseResult struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a blob for write and delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (result AcquireLeaseResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "AcquireLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID != nil && *input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseID` cannot be an empty string, if specified.")
}
if input.ProposedLeaseID != nil && *input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.ProposedLeaseID` cannot be an empty string, if specified.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("blobs.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.ProposedLeaseID != nil {
headers["x-ms-proposed-lease-id"] = *input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResult, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/lease_break.go 0000664 0000000 0000000 00000010614 14232154237 0022710 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks an existing lock on a blob using the LeaseID.
func (client Client) BreakLease(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "BreakLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`blobName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("blobs.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/lease_change.go 0000664 0000000 0000000 00000007777 14232154237 0023071 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes an existing lock on a blob for another lock.
func (client Client) ChangeLease(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ChangeLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`blobName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("blobs.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName, containerName, blobName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil && resp.Header != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/lease_release.go 0000664 0000000 0000000 00000006720 14232154237 0023247 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases a lock based on the Lease ID.
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/lease_renew.go 0000664 0000000 0000000 00000006555 14232154237 0022755 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
func (client Client) RenewLease(ctx context.Context, accountName, containerName, blobName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "RenewLease", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`blobName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("blobs.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, blobName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName, containerName, blobName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/lease_test.go 0000664 0000000 0000000 00000007152 14232154237 0022606 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLeaseLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "ubuntu.iso"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
defer blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{})
// Test begins here
t.Logf("[DEBUG] Acquiring Lease..")
leaseInput := AcquireLeaseInput{
LeaseDuration: -1,
}
leaseInfo, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Changing Lease..")
changeLeaseInput := ChangeLeaseInput{
ExistingLeaseID: leaseInfo.LeaseID,
ProposedLeaseID: "31f5bb01-cdd9-4166-bcdc-95186076bde0",
}
changeLeaseResult, err := blobClient.ChangeLease(ctx, accountName, containerName, fileName, changeLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
t.Logf("[DEBUG] New Lease ID: %q", changeLeaseResult.LeaseID)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, changeLeaseResult.LeaseID); err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Acquiring a new lease..")
leaseInput = AcquireLeaseInput{
LeaseDuration: 30,
}
leaseInfo, err = blobClient.AcquireLease(ctx, accountName, containerName, fileName, leaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseInfo.LeaseID)
t.Logf("[DEBUG] Renewing lease..")
if _, err := blobClient.RenewLease(ctx, accountName, containerName, fileName, leaseInfo.LeaseID); err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
t.Logf("[DEBUG] Breaking lease..")
breakLeaseInput := BreakLeaseInput{
LeaseID: leaseInfo.LeaseID,
}
if _, err := blobClient.BreakLease(ctx, accountName, containerName, fileName, breakLeaseInput); err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/lifecycle_test.go 0000664 0000000 0000000 00000012612 14232154237 0023451 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageBlob = Client{}
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
defer containersClient.Delete(ctx, accountName, containerName)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] Retrieving Blob Properties..")
details, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 0 {
t.Fatalf("Expected there to be no items of metadata but got %d", len(details.MetaData))
}
t.Logf("[DEBUG] Checking it's returned in the List API..")
listInput := containers.ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 1 {
t.Fatalf("Expected there to be 1 blob in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Setting MetaData..")
metaDataInput := SetMetaDataInput{
MetaData: map[string]string{
"hello": "there",
},
}
if _, err := blobClient.SetMetaData(ctx, accountName, containerName, fileName, metaDataInput); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
// default value
if details.AccessTier != Hot {
t.Fatalf("Expected the AccessTier to be %q but got %q", Hot, details.AccessTier)
}
if details.BlobType != BlockBlob {
t.Fatalf("Expected BlobType to be %q but got %q", BlockBlob, details.BlobType)
}
if len(details.MetaData) != 1 {
t.Fatalf("Expected there to be 1 item of metadata but got %d", len(details.MetaData))
}
if details.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", details.MetaData["there"])
}
t.Logf("[DEBUG] Retrieving the Block List..")
getBlockListInput := GetBlockListInput{
BlockListType: All,
}
blockList, err := blobClient.GetBlockList(ctx, accountName, containerName, fileName, getBlockListInput)
if err != nil {
t.Fatalf("Error retrieving Block List: %s", err)
}
// since this is a copy from an existing file, all blocks should be present
if len(blockList.CommittedBlocks.Blocks) == 0 {
t.Fatalf("Expected there to be committed blocks but there weren't!")
}
if len(blockList.UncommittedBlocks.Blocks) != 0 {
t.Fatalf("Expected all blocks to be committed but got %d uncommitted blocks", len(blockList.UncommittedBlocks.Blocks))
}
t.Logf("[DEBUG] Changing the Access Tiers..")
tiers := []AccessTier{
Hot,
Cool,
Archive,
}
for _, tier := range tiers {
t.Logf("[DEBUG] Updating the Access Tier to %q..", string(tier))
if _, err := blobClient.SetTier(ctx, accountName, containerName, fileName, tier); err != nil {
t.Fatalf("Error setting the Access Tier: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Blob Properties..")
details, err = blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error re-retrieving properties: %s", err)
}
if details.AccessTier != tier {
t.Fatalf("Expected the AccessTier to be %q but got %q", tier, details.AccessTier)
}
}
t.Logf("[DEBUG] Deleting Blob")
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, DeleteInput{}); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/metadata_set.go 0000664 0000000 0000000 00000007724 14232154237 0023116 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SetMetaDataInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// Any metadata which should be added to this blob
MetaData map[string]string
}
// SetMetaData marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
func (client Client) SetMetaData(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "GetProperties", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, containerName, blobName string, input SetMetaDataInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/models.go 0000664 0000000 0000000 00000002714 14232154237 0021740 0 ustar 00root root 0000000 0000000 package blobs
type AccessTier string
var (
Archive AccessTier = "Archive"
Cool AccessTier = "Cool"
Hot AccessTier = "Hot"
)
type ArchiveStatus string
var (
None ArchiveStatus = ""
RehydratePendingToCool ArchiveStatus = "rehydrate-pending-to-cool"
RehydratePendingToHot ArchiveStatus = "rehydrate-pending-to-hot"
)
type BlockListType string
var (
All BlockListType = "all"
Committed BlockListType = "committed"
Uncommitted BlockListType = "uncommitted"
)
type Block struct {
// The base64-encoded Block ID
Name string `xml:"Name"`
// The size of the Block in Bytes
Size int64 `xml:"Size"`
}
type BlobType string
var (
AppendBlob BlobType = "AppendBlob"
BlockBlob BlobType = "BlockBlob"
PageBlob BlobType = "PageBlob"
)
type CommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
type CopyStatus string
var (
Aborted CopyStatus = "aborted"
Failed CopyStatus = "failed"
Pending CopyStatus = "pending"
Success CopyStatus = "success"
)
type LeaseDuration string
var (
Fixed LeaseDuration = "fixed"
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
type UncommittedBlocks struct {
Blocks []Block `xml:"Block"`
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/properties_get.go 0000664 0000000 0000000 00000031314 14232154237 0023506 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
}
type GetPropertiesResult struct {
autorest.Response
// The tier of page blob on a premium storage account or tier of block blob on blob storage or general purpose v2 account.
AccessTier AccessTier
// This gives the last time tier was changed on the object.
// This header is returned only if tier on block blob was ever set.
// The date format follows RFC 1123
AccessTierChangeTime string
// For page blobs on a premium storage account only.
// If the access tier is not explicitly set on the blob, the tier is inferred based on its content length
// and this header will be returned with true value.
// For block blobs on Blob Storage or general purpose v2 account, if the blob does not have the access tier
// set then we infer the tier from the storage account properties. This header is set only if the block blob
// tier is inferred
AccessTierInferred bool
// For blob storage or general purpose v2 account.
// If the blob is being rehydrated and is not complete then this header is returned indicating
// that rehydrate is pending and also tells the destination tier
ArchiveStatus ArchiveStatus
// The number of committed blocks present in the blob.
// This header is returned only for append blobs.
BlobCommittedBlockCount string
// The current sequence number for a page blob.
// This header is not returned for block blobs or append blobs.
// This header is not returned for block blobs.
BlobSequenceNumber string
// The blob type.
BlobType BlobType
// If the Cache-Control request header has previously been set for the blob, that value is returned in this header.
CacheControl string
// The Content-Disposition response header field conveys additional information about how to process
// the response payload, and also can be used to attach additional metadata.
// For example, if set to attachment, it indicates that the user-agent should not display the response,
// but instead show a Save As dialog.
ContentDisposition string
// If the Content-Encoding request header has previously been set for the blob,
// that value is returned in this header.
ContentEncoding string
// If the Content-Language request header has previously been set for the blob,
// that value is returned in this header.
ContentLanguage string
// The size of the blob in bytes.
// For a page blob, this header returns the value of the x-ms-blob-content-length header stored with the blob.
ContentLength int64
// The content type specified for the blob.
// If no content type was specified, the default content type is `application/octet-stream`.
ContentType string
// If the Content-MD5 header has been set for the blob, this response header is returned so that
// the client can check for message content integrity.
ContentMD5 string
// Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob.
// This value can specify the time of a completed, aborted, or failed copy attempt.
// This header does not appear if a copy is pending, if this blob has never been the
// destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob
// operation using Set Blob Properties, Put Blob, or Put Block List.
CopyCompletionTime string
// Included if the blob is incremental copy blob or incremental copy snapshot, if x-ms-copy-status is success.
// Snapshot time of the last successful incremental copy snapshot for this blob
CopyDestinationSnapshot string
// String identifier for the last attempted Copy Blob operation where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyID string
// Contains the number of bytes copied and the total bytes in the source in the last attempted
// Copy Blob operation where this blob was the destination blob.
// Can show between 0 and Content-Length bytes copied.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyProgress string
// URL up to 2 KB in length that specifies the source blob used in the last attempted Copy Blob operation
// where this blob was the destination blob.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List
CopySource string
// State of the copy operation identified by x-ms-copy-id, with these values:
// - success: Copy completed successfully.
// - pending: Copy is in progress.
// Check x-ms-copy-status-description if intermittent, non-fatal errors
// impede copy progress but don’t cause failure.
// - aborted: Copy was ended by Abort Copy Blob.
// - failed: Copy failed. See x-ms- copy-status-description for failure details.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a completed Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatus CopyStatus
// Describes cause of fatal or non-fatal copy operation failure.
// This header does not appear if this blob has never been the destination in a Copy Blob operation,
// or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties,
// Put Blob, or Put Block List.
CopyStatusDescription string
// The date/time at which the blob was created. The date format follows RFC 1123
CreationTime string
// The ETag contains a value that you can use to perform operations conditionally
ETag string
// Included if the blob is incremental copy blob.
IncrementalCopy bool
// The date/time that the blob was last modified. The date format follows RFC 1123.
LastModified string
// When a blob is leased, specifies whether the lease is of infinite or fixed duration
LeaseDuration LeaseDuration
// The lease state of the blob
LeaseState LeaseState
LeaseStatus LeaseStatus
// A set of name-value pairs that correspond to the user-defined metadata associated with this blob
MetaData map[string]string
// Is the Storage Account encrypted using server-side encryption? This should always return true
ServerEncrypted bool
}
// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the blob
func (client Client) GetProperties(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.AccessTier = AccessTier(resp.Header.Get("x-ms-access-tier"))
result.AccessTierChangeTime = resp.Header.Get(" x-ms-access-tier-change-time")
result.ArchiveStatus = ArchiveStatus(resp.Header.Get(" x-ms-archive-status"))
result.BlobCommittedBlockCount = resp.Header.Get("x-ms-blob-committed-block-count")
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.BlobType = BlobType(resp.Header.Get("x-ms-blob-type"))
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.CopyDestinationSnapshot = resp.Header.Get("x-ms-copy-destination-snapshot")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = CopyStatus(resp.Header.Get("x-ms-copy-status"))
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CreationTime = resp.Header.Get("x-ms-creation-time")
result.ETag = resp.Header.Get("Etag")
result.LastModified = resp.Header.Get("Last-Modified")
result.LeaseDuration = LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.MetaData = metadata.ParseFromHeaders(resp.Header)
if v := resp.Header.Get("x-ms-access-tier-inferred"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.AccessTierInferred = b
}
if v := resp.Header.Get("Content-Length"); v != "" {
i, innerErr := strconv.Atoi(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as an integer: %s", v, innerErr)
}
result.ContentLength = int64(i)
}
if v := resp.Header.Get("x-ms-incremental-copy"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
if v := resp.Header.Get("x-ms-server-encrypted"); v != "" {
b, innerErr := strconv.ParseBool(v)
if innerErr != nil {
err = fmt.Errorf("Error parsing %q as a bool: %s", v, innerErr)
return
}
result.IncrementalCopy = b
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/properties_set.go 0000664 0000000 0000000 00000012111 14232154237 0023514 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
CacheControl *string
ContentType *string
ContentMD5 *string
ContentEncoding *string
ContentLanguage *string
LeaseID *string
ContentDisposition *string
ContentLength *int64
SequenceNumberAction *SequenceNumberAction
BlobSequenceNumber *string
}
type SetPropertiesResult struct {
autorest.Response
BlobSequenceNumber string
Etag string
}
// SetProperties sets system properties on the blob.
func (client Client) SetProperties(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (result SetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetProperties", "`blobName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
type SequenceNumberAction string
var (
Increment SequenceNumberAction = "increment"
Max SequenceNumberAction = "max"
Update SequenceNumberAction = "update"
)
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.ContentLength != nil {
headers["x-ms-blob-content-length"] = *input.ContentLength
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.SequenceNumberAction != nil {
headers["x-ms-sequence-number-action"] = string(*input.SequenceNumberAction)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result SetPropertiesResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.Etag = resp.Header.Get("Etag")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_append_blob.go 0000664 0000000 0000000 00000011323 14232154237 0023606 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutAppendBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutAppendBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new append blob, or updates the content of an existing blob.
func (client Client) PutAppendBlob(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutAppendBlob", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutAppendBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutAppendBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutAppendBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure sending request")
return
}
result, err = client.PutAppendBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutAppendBlob", resp, "Failure responding to request")
return
}
return
}
// PutAppendBlobPreparer prepares the PutAppendBlob request.
func (client Client) PutAppendBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutAppendBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(AppendBlob),
"x-ms-version": APIVersion,
// For a page blob or an append blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutAppendBlobSender sends the PutAppendBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutAppendBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutAppendBlobResponder handles the response to the PutAppendBlob request. The method always
// closes the http.Response Body.
func (client Client) PutAppendBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_block.go 0000664 0000000 0000000 00000010100 14232154237 0022423 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockInput struct {
BlockID string
Content []byte
ContentMD5 *string
LeaseID *string
}
type PutBlockResult struct {
autorest.Response
ContentMD5 string
}
// PutBlock creates a new block to be committed as part of a blob.
func (client Client) PutBlock(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (result PutBlockResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlock", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.BlockID` cannot be an empty string.")
}
if len(input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlock", "`input.Content` cannot be empty.")
}
req, err := client.PutBlockPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure sending request")
return
}
result, err = client.PutBlockResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlock", resp, "Failure responding to request")
return
}
return
}
// PutBlockPreparer prepares the PutBlock request.
func (client Client) PutBlockPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Content-Length": int(len(input.Content)),
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockSender sends the PutBlock request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockResponder handles the response to the PutBlock request. The method always
// closes the http.Response Body.
func (client Client) PutBlockResponder(resp *http.Response) (result PutBlockResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_block_blob.go 0000664 0000000 0000000 00000011750 14232154237 0023435 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutBlockBlobInput struct {
CacheControl *string
Content *[]byte
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
}
// PutBlockBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block append blob, or updates the content of an existing block blob.
func (client Client) PutBlockBlob(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`blobName` cannot be an empty string.")
}
if input.Content != nil && len(*input.Content) == 0 {
return result, validation.NewError("blobs.Client", "PutBlockBlob", "`input.Content` must either be nil or not empty.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "PutBlockBlob", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.PutBlockBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure sending request")
return
}
result, err = client.PutBlockBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockBlob", resp, "Failure responding to request")
return
}
return
}
// PutBlockBlobPreparer prepares the PutBlockBlob request.
func (client Client) PutBlockBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(BlockBlob),
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Content != nil {
headers["Content-Length"] = int(len(*input.Content))
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
decorators := []autorest.PrepareDecorator{
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
}
if input.Content != nil {
decorators = append(decorators, autorest.WithBytes(input.Content))
}
preparer := autorest.CreatePreparer(decorators...)
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockBlobSender sends the PutBlockBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockBlobResponder handles the response to the PutBlockBlob request. The method always
// closes the http.Response Body.
func (client Client) PutBlockBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_block_blob_file.go 0000664 0000000 0000000 00000001510 14232154237 0024425 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"io"
"os"
)
// PutBlockBlobFromFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutBlockBlobFromFile(ctx context.Context, accountName, containerName, blobName string, file *os.File, input PutBlockBlobInput) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
bytes := make([]byte, fileSize)
_, err = file.ReadAt(bytes, 0)
if err != nil {
if err != io.EOF {
return fmt.Errorf("Error reading bytes: %s", err)
}
}
input.Content = &bytes
if _, err = client.PutBlockBlob(ctx, accountName, containerName, blobName, input); err != nil {
return fmt.Errorf("Error putting bytes: %s", err)
}
return nil
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_block_list.go 0000664 0000000 0000000 00000012220 14232154237 0023463 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type BlockList struct {
CommittedBlockIDs []BlockID `xml:"Committed,omitempty"`
UncommittedBlockIDs []BlockID `xml:"Uncommitted,omitempty"`
LatestBlockIDs []BlockID `xml:"Latest,omitempty"`
}
type BlockID struct {
Value string `xml:",chardata"`
}
type PutBlockListInput struct {
BlockList BlockList
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
MetaData map[string]string
LeaseID *string
}
type PutBlockListResult struct {
autorest.Response
ContentMD5 string
ETag string
LastModified string
}
// PutBlockList 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.
func (client Client) PutBlockList(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (result PutBlockListResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockList", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockList", "`blobName` cannot be an empty string.")
}
req, err := client.PutBlockListPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure sending request")
return
}
result, err = client.PutBlockListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockList", resp, "Failure responding to request")
return
}
return
}
// PutBlockListPreparer prepares the PutBlockList request.
func (client Client) PutBlockListPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockListInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "blocklist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(input.BlockList))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockListSender sends the PutBlockList request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockListResponder handles the response to the PutBlockList request. The method always
// closes the http.Response Body.
func (client Client) PutBlockListResponder(resp *http.Response) (result PutBlockListResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ETag = resp.Header.Get("ETag")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_block_url.go 0000664 0000000 0000000 00000010564 14232154237 0023323 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutBlockFromURLInput struct {
BlockID string
CopySource string
ContentMD5 *string
LeaseID *string
Range *string
}
type PutBlockFromURLResult struct {
autorest.Response
ContentMD5 string
}
// PutBlockFromURL creates a new block to be committed as part of a blob where the contents are read from a URL
func (client Client) PutBlockFromURL(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (result PutBlockFromURLResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`blobName` cannot be an empty string.")
}
if input.BlockID == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.BlockID` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("blobs.Client", "PutBlockFromURL", "`input.CopySource` cannot be an empty string.")
}
req, err := client.PutBlockFromURLPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", nil, "Failure preparing request")
return
}
resp, err := client.PutBlockFromURLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure sending request")
return
}
result, err = client.PutBlockFromURLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutBlockFromURL", resp, "Failure responding to request")
return
}
return
}
// PutBlockFromURLPreparer prepares the PutBlockFromURL request.
func (client Client) PutBlockFromURLPreparer(ctx context.Context, accountName, containerName, blobName string, input PutBlockFromURLInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "block"),
"blockid": autorest.Encode("query", input.BlockID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
if input.ContentMD5 != nil {
headers["x-ms-source-content-md5"] = *input.ContentMD5
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.Range != nil {
headers["x-ms-source-range"] = *input.Range
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutBlockFromURLSender sends the PutBlockFromURL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutBlockFromURLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutBlockFromURLResponder handles the response to the PutBlockFromURL request. The method always
// closes the http.Response Body.
func (client Client) PutBlockFromURLResponder(resp *http.Response) (result PutBlockFromURLResult, err error) {
if resp != nil && resp.Header != nil {
result.ContentMD5 = resp.Header.Get("Content-MD5")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_page_blob.go 0000664 0000000 0000000 00000012264 14232154237 0023260 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type PutPageBlobInput struct {
CacheControl *string
ContentDisposition *string
ContentEncoding *string
ContentLanguage *string
ContentMD5 *string
ContentType *string
LeaseID *string
MetaData map[string]string
BlobContentLengthBytes int64
BlobSequenceNumber *int64
AccessTier *AccessTier
}
// PutPageBlob is a wrapper around the Put API call (with a stricter input object)
// which creates a new block blob, or updates the content of an existing page blob.
func (client Client) PutPageBlob(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`blobName` cannot be an empty string.")
}
if input.BlobContentLengthBytes == 0 || input.BlobContentLengthBytes%512 != 0 {
return result, validation.NewError("blobs.Client", "PutPageBlob", "`input.BlobContentLengthBytes` must be aligned to a 512-byte boundary.")
}
req, err := client.PutPageBlobPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", nil, "Failure preparing request")
return
}
resp, err := client.PutPageBlobSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure sending request")
return
}
result, err = client.PutPageBlobResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageBlob", resp, "Failure responding to request")
return
}
return
}
// PutPageBlobPreparer prepares the PutPageBlob request.
func (client Client) PutPageBlobPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageBlobInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
headers := map[string]interface{}{
"x-ms-blob-type": string(PageBlob),
"x-ms-version": APIVersion,
// For a page blob or an page blob, the value of this header must be set to zero,
// as Put Blob is used only to initialize the blob
"Content-Length": 0,
// This header specifies the maximum size for the page blob, up to 8 TB.
// The page blob size must be aligned to a 512-byte boundary.
"x-ms-blob-content-length": input.BlobContentLengthBytes,
}
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
if input.BlobSequenceNumber != nil {
headers["x-ms-blob-sequence-number"] = *input.BlobSequenceNumber
}
if input.CacheControl != nil {
headers["x-ms-blob-cache-control"] = *input.CacheControl
}
if input.ContentDisposition != nil {
headers["x-ms-blob-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-blob-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-blob-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-blob-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-blob-content-type"] = *input.ContentType
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageBlobSender sends the PutPageBlob request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageBlobSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageBlobResponder handles the response to the PutPageBlob request. The method always
// closes the http.Response Body.
func (client Client) PutPageBlobResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_page_clear.go 0000664 0000000 0000000 00000007556 14232154237 0023440 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageClearInput struct {
StartByte int64
EndByte int64
LeaseID *string
}
// PutPageClear clears a range of pages within a page blob.
func (client Client) PutPageClear(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageClear", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageClear", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageClear", "`input.EndByte` must be greater than 0.")
}
req, err := client.PutPageClearPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", nil, "Failure preparing request")
return
}
resp, err := client.PutPageClearSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure sending request")
return
}
result, err = client.PutPageClearResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageClear", resp, "Failure responding to request")
return
}
return
}
// PutPageClearPreparer prepares the PutPageClear request.
func (client Client) PutPageClearPreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageClearInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageClearSender sends the PutPageClear request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageClearSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageClearResponder handles the response to the PutPageClear request. The method always
// closes the http.Response Body.
func (client Client) PutPageClearResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/put_page_update.go 0000664 0000000 0000000 00000012777 14232154237 0023635 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutPageUpdateInput struct {
StartByte int64
EndByte int64
Content []byte
IfSequenceNumberEQ *string
IfSequenceNumberLE *string
IfSequenceNumberLT *string
IfModifiedSince *string
IfUnmodifiedSince *string
IfMatch *string
IfNoneMatch *string
LeaseID *string
}
type PutPageUpdateResult struct {
autorest.Response
BlobSequenceNumber string
ContentMD5 string
LastModified string
}
// PutPageUpdate writes a range of pages to a page blob.
func (client Client) PutPageUpdate(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (result PutPageUpdateResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`blobName` cannot be an empty string.")
}
if input.StartByte < 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.StartByte` must be greater than or equal to 0.")
}
if input.EndByte <= 0 {
return result, validation.NewError("blobs.Client", "PutPageUpdate", "`input.EndByte` must be greater than 0.")
}
expectedSize := (input.EndByte - input.StartByte) + 1
actualSize := int64(len(input.Content))
if expectedSize != actualSize {
return result, validation.NewError("blobs.Client", "PutPageUpdate", fmt.Sprintf("Content Size was defined as %d but got %d.", expectedSize, actualSize))
}
req, err := client.PutPageUpdatePreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", nil, "Failure preparing request")
return
}
resp, err := client.PutPageUpdateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure sending request")
return
}
result, err = client.PutPageUpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "PutPageUpdate", resp, "Failure responding to request")
return
}
return
}
// PutPageUpdatePreparer prepares the PutPageUpdate request.
func (client Client) PutPageUpdatePreparer(ctx context.Context, accountName, containerName, blobName string, input PutPageUpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "page"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-page-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartByte, input.EndByte),
"Content-Length": int(len(input.Content)),
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfSequenceNumberEQ != nil {
headers["x-ms-if-sequence-number-eq"] = *input.IfSequenceNumberEQ
}
if input.IfSequenceNumberLE != nil {
headers["x-ms-if-sequence-number-le"] = *input.IfSequenceNumberLE
}
if input.IfSequenceNumberLT != nil {
headers["x-ms-if-sequence-number-lt"] = *input.IfSequenceNumberLT
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutPageUpdateSender sends the PutPageUpdate request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutPageUpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutPageUpdateResponder handles the response to the PutPageUpdate request. The method always
// closes the http.Response Body.
func (client Client) PutPageUpdateResponder(resp *http.Response) (result PutPageUpdateResult, err error) {
if resp != nil && resp.Header != nil {
result.BlobSequenceNumber = resp.Header.Get("x-ms-blob-sequence-number")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.LastModified = resp.Header.Get("Last-Modified")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/resource_id.go 0000664 0000000 0000000 00000003060 14232154237 0022753 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Blob
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName, blobName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, containerName, blobName)
}
type ResourceID struct {
AccountName string
ContainerName string
BlobName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Blob Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar/example.vhd
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
containerName := segments[0]
blobName := strings.TrimPrefix(path, containerName)
blobName = strings.TrimPrefix(blobName, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
BlobName: blobName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/resource_id_test.go 0000664 0000000 0000000 00000006670 14232154237 0024024 0 ustar 00root root 0000000 0000000 package blobs
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1", "blob1.vhd")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/blob1.vhd",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "blob1.vhd" {
t.Fatalf("Expected Blob Name to be `blob1.vhd` but got %q", actual.BlobName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1/example/blob1.vhd",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1/example/blob1.vhd",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1/example/blob1.vhd",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1/example/blob1.vhd",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected Container Name to be `container1` but got %q", actual.ContainerName)
}
if actual.BlobName != "example/blob1.vhd" {
t.Fatalf("Expected Blob Name to be `example/blob1.vhd` but got %q", actual.BlobName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/set_tier.go 0000664 0000000 0000000 00000006325 14232154237 0022275 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetTier sets the tier on a blob.
func (client Client) SetTier(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "SetTier", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "SetTier", "`blobName` cannot be an empty string.")
}
req, err := client.SetTierPreparer(ctx, accountName, containerName, blobName, tier)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", nil, "Failure preparing request")
return
}
resp, err := client.SetTierSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure sending request")
return
}
result, err = client.SetTierResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "SetTier", resp, "Failure responding to request")
return
}
return
}
// SetTierPreparer prepares the SetTier request.
func (client Client) SetTierPreparer(ctx context.Context, accountName, containerName, blobName string, tier AccessTier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "tier"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-access-tier": string(tier),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetTierSender sends the SetTier request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetTierSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetTierResponder handles the response to the SetTier request. The method always
// closes the http.Response Body.
func (client Client) SetTierResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/snapshot.go 0000664 0000000 0000000 00000013463 14232154237 0022317 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SnapshotInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// MetaData is a user-defined name-value pair associated with the blob.
// If no name-value pairs are specified, the operation will copy the base blob metadata to the snapshot.
// If one or more name-value pairs are specified, the snapshot is created with the specified metadata,
// and metadata is not copied from the base blob.
MetaData map[string]string
// A DateTime value which will only snapshot the blob if it has been modified since the specified date/time
// If the base blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
IfModifiedSince *string
// A DateTime value which will only snapshot the blob if it has not been modified since the specified date/time
// If the base blob has been modified, the Blob service returns status code 412 (Precondition Failed).
IfUnmodifiedSince *string
// An ETag value to snapshot the blob only if its ETag value matches the value specified.
// If the values do not match, the Blob service returns status code 412 (Precondition Failed).
IfMatch *string
// An ETag value for this conditional header to snapshot the blob only if its ETag value
// does not match the value specified.
// If the values are identical, the Blob service returns status code 412 (Precondition Failed).
IfNoneMatch *string
}
type SnapshotResult struct {
autorest.Response
// The ETag of the snapshot
ETag string
// A DateTime value that uniquely identifies the snapshot.
// The value of this header indicates the snapshot version,
// and may be used in subsequent requests to access the snapshot.
SnapshotDateTime string
}
// Snapshot captures a Snapshot of a given Blob
func (client Client) Snapshot(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (result SnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Snapshot", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Snapshot", "`blobName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("blobs.Client", "Snapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.SnapshotPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", nil, "Failure preparing request")
return
}
resp, err := client.SnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure sending request")
return
}
result, err = client.SnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Snapshot", resp, "Failure responding to request")
return
}
return
}
// SnapshotPreparer prepares the Snapshot request.
func (client Client) SnapshotPreparer(ctx context.Context, accountName, containerName, blobName string, input SnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
if input.IfMatch != nil {
headers["If-Match"] = *input.IfMatch
}
if input.IfNoneMatch != nil {
headers["If-None-Match"] = *input.IfNoneMatch
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SnapshotSender sends the Snapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SnapshotResponder handles the response to the Snapshot request. The method always
// closes the http.Response Body.
func (client Client) SnapshotResponder(resp *http.Response) (result SnapshotResult, err error) {
if resp != nil && resp.Header != nil {
result.ETag = resp.Header.Get("ETag")
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/snapshot_get_properties.go 0000664 0000000 0000000 00000006445 14232154237 0025434 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetSnapshotPropertiesInput struct {
// The ID of the Lease
// This must be specified if a Lease is present on the Blob, else a 403 is returned
LeaseID *string
// The ID of the Snapshot which should be retrieved
SnapshotID string
}
// GetSnapshotProperties returns all user-defined metadata, standard HTTP properties, and system properties for
// the specified snapshot of a blob
func (client Client) GetSnapshotProperties(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`blobName` cannot be an empty string.")
}
if input.SnapshotID == "" {
return result, validation.NewError("blobs.Client", "GetSnapshotProperties", "`input.SnapshotID` cannot be an empty string.")
}
req, err := client.GetSnapshotPropertiesPreparer(ctx, accountName, containerName, blobName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", nil, "Failure preparing request")
return
}
// we re-use the GetProperties methods since this is otherwise the same
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "GetSnapshotProperties", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPropertiesPreparer(ctx context.Context, accountName, containerName, blobName string, input GetSnapshotPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"snapshot": autorest.Encode("query", input.SnapshotID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.LeaseID != nil {
headers["x-ms-lease-id"] = *input.LeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/snapshot_test.go 0000664 0000000 0000000 00000013411 14232154237 0023347 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"fmt"
"net/http"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/containers"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestSnapshotLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
fileName := "example.txt"
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
containersClient := containers.NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithStorageResourceManagerAuth(containersClient.Client)
_, err = containersClient.Create(ctx, accountName, containerName, containers.CreateInput{})
if err != nil {
t.Fatalf("Error creating: %s", err)
}
defer containersClient.Delete(ctx, accountName, containerName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
blobClient := NewWithEnvironment(client.Environment)
blobClient.Client = client.PrepareWithAuthorizer(blobClient.Client, storageAuth)
t.Logf("[DEBUG] Copying file to Blob Storage..")
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
refreshInterval := 5 * time.Second
if err := blobClient.CopyAndWait(ctx, accountName, containerName, fileName, copyInput, refreshInterval); err != nil {
t.Fatalf("Error copying: %s", err)
}
t.Logf("[DEBUG] First Snapshot..")
firstSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{})
if err != nil {
t.Fatalf("Error taking first snapshot: %s", err)
}
t.Logf("[DEBUG] First Snapshot ID: %q", firstSnapshot.SnapshotDateTime)
t.Log("[DEBUG] Waiting 2 seconds..")
time.Sleep(2 * time.Second)
t.Logf("[DEBUG] Second Snapshot..")
secondSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
MetaData: map[string]string{
"hello": "world",
},
})
if err != nil {
t.Fatalf("Error taking Second snapshot: %s", err)
}
t.Logf("[DEBUG] Second Snapshot ID: %q", secondSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Leasing the Blob..")
leaseDetails, err := blobClient.AcquireLease(ctx, accountName, containerName, fileName, AcquireLeaseInput{
// infinite
LeaseDuration: -1,
})
if err != nil {
t.Fatalf("Error leasing Blob: %s", err)
}
t.Logf("[DEBUG] Lease ID: %q", leaseDetails.LeaseID)
t.Logf("[DEBUG] Third Snapshot..")
thirdSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
})
if err != nil {
t.Fatalf("Error taking Third snapshot: %s", err)
}
t.Logf("[DEBUG] Third Snapshot ID: %q", thirdSnapshot.SnapshotDateTime)
t.Logf("[DEBUG] Releasing Lease..")
if _, err := blobClient.ReleaseLease(ctx, accountName, containerName, fileName, leaseDetails.LeaseID); err != nil {
t.Fatalf("Error releasing Lease: %s", err)
}
// get the properties from the blob, which should include the LastModifiedDate
t.Logf("[DEBUG] Retrieving Properties for Blob")
props, err := blobClient.GetProperties(ctx, accountName, containerName, fileName, GetPropertiesInput{})
if err != nil {
t.Fatalf("Error getting properties: %s", err)
}
// confirm that the If-Modified-None returns an error
t.Logf("[DEBUG] Third Snapshot..")
fourthSnapshot, err := blobClient.Snapshot(ctx, accountName, containerName, fileName, SnapshotInput{
LeaseID: &leaseDetails.LeaseID,
IfModifiedSince: &props.LastModified,
})
if err == nil {
t.Fatalf("Expected an error but didn't get one")
}
if fourthSnapshot.Response.StatusCode != http.StatusPreconditionFailed {
t.Fatalf("Expected the status code to be Precondition Failed but got: %d", fourthSnapshot.Response.StatusCode)
}
t.Logf("[DEBUG] Retrieving the Second Snapshot Properties..")
getSecondSnapshotInput := GetSnapshotPropertiesInput{
SnapshotID: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput); err != nil {
t.Fatalf("Error retrieving properties for the second snapshot: %s", err)
}
t.Logf("[DEBUG] Deleting the Second Snapshot..")
deleteSnapshotInput := DeleteSnapshotInput{
SnapshotDateTime: secondSnapshot.SnapshotDateTime,
}
if _, err := blobClient.DeleteSnapshot(ctx, accountName, containerName, fileName, deleteSnapshotInput); err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Second Snapshot Properties..")
secondSnapshotProps, err := blobClient.GetSnapshotProperties(ctx, accountName, containerName, fileName, getSecondSnapshotInput)
if err == nil {
t.Fatalf("Expected an error retrieving the snapshot but got none")
}
if secondSnapshotProps.Response.StatusCode != http.StatusNotFound {
t.Fatalf("Expected the status code to be %d but got %q", http.StatusNoContent, secondSnapshotProps.Response.StatusCode)
}
t.Logf("[DEBUG] Deleting all the snapshots..")
if _, err := blobClient.DeleteSnapshots(ctx, accountName, containerName, fileName, DeleteSnapshotsInput{}); err != nil {
t.Fatalf("Error deleting snapshots: %s", err)
}
t.Logf("[DEBUG] Deleting the Blob..")
deleteInput := DeleteInput{
DeleteSnapshots: false,
}
if _, err := blobClient.Delete(ctx, accountName, containerName, fileName, deleteInput); err != nil {
t.Fatalf("Error deleting Blob: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/undelete.go 0000664 0000000 0000000 00000006323 14232154237 0022262 0 ustar 00root root 0000000 0000000 package blobs
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Undelete restores the contents and metadata of soft deleted blob and any associated soft deleted snapshots.
func (client Client) Undelete(ctx context.Context, accountName, containerName, blobName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` cannot be an empty string.")
}
if strings.ToLower(containerName) != containerName {
return result, validation.NewError("blobs.Client", "Undelete", "`containerName` must be a lower-cased string.")
}
if blobName == "" {
return result, validation.NewError("blobs.Client", "Undelete", "`blobName` cannot be an empty string.")
}
req, err := client.UndeletePreparer(ctx, accountName, containerName, blobName)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", nil, "Failure preparing request")
return
}
resp, err := client.UndeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure sending request")
return
}
result, err = client.UndeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "blobs.Client", "Undelete", resp, "Failure responding to request")
return
}
return
}
// UndeletePreparer prepares the Undelete request.
func (client Client) UndeletePreparer(ctx context.Context, accountName, containerName, blobName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
"blobName": autorest.Encode("path", blobName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "undelete"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}/{blobName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UndeleteSender sends the Undelete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UndeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UndeleteResponder handles the response to the Undelete request. The method always
// closes the http.Response Body.
func (client Client) UndeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/blobs/version.go 0000664 0000000 0000000 00000000463 14232154237 0022141 0 ustar 00root root 0000000 0000000 package blobs
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/ 0000775 0000000 0000000 00000000000 14232154237 0021166 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/blob/containers/README.md 0000664 0000000 0000000 00000002257 14232154237 0022453 0 ustar 00root root 0000000 0000000 ## Blob Storage Container SDK for API version 2020-08-04
This package allows you to interact with the Containers Blob Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
Note: when using the `ListBlobs` operation, only `SharedKeyLite` authentication is supported.
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/blob/containers"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
containerName := "mycontainer"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
containersClient := containers.New()
containersClient.Client.Authorizer = storageAuth
ctx := context.TODO()
createInput := containers.CreateInput{
AccessLevel: containers.Private,
}
if _, err := containersClient.Create(ctx, accountName, containerName, createInput); err != nil {
return fmt.Errorf("Error creating Container: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/blob/containers/api.go 0000664 0000000 0000000 00000003675 14232154237 0022301 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageContainer interface {
Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error)
Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error)
GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error)
GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error)
AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error)
BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error)
ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error)
ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error)
RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error)
ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error)
GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, containerName string) string
SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error)
SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error)
SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error)
SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/client.go 0000664 0000000 0000000 00000001632 14232154237 0022775 0 ustar 00root root 0000000 0000000 package containers
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Blob Storage Containers.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithBaseURI creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
func (client Client) setAccessLevelIntoHeaders(headers map[string]interface{}, level AccessLevel) map[string]interface{} {
// If this header is not included in the request, container data is private to the account owner.
if level != Private {
headers["x-ms-blob-public-access"] = string(level)
}
return headers
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/create.go 0000664 0000000 0000000 00000010233 14232154237 0022757 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// Specifies whether data in the container may be accessed publicly and the level of access
AccessLevel AccessLevel
// A name-value pair to associate with the container as metadata.
MetaData map[string]string
}
type CreateResponse struct {
autorest.Response
Error *ErrorResponse `xml:"Error"`
}
// Create creates a new container under the specified account.
// If the container with the same name already exists, the operation fails.
func (client Client) Create(ctx context.Context, accountName, containerName string, input CreateInput) (result CreateResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Create", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Create", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("containers.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, containerName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, input.AccessLevel)
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result CreateResponse, err error) {
successfulStatusCodes := []int{
http.StatusCreated,
}
if autorest.ResponseHasStatusCode(resp, successfulStatusCodes...) {
// when successful there's no response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
} else {
// however when there's an error the error's in the response
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(successfulStatusCodes...),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/delete.go 0000664 0000000 0000000 00000005600 14232154237 0022760 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete marks the specified container for deletion.
// The container and any blobs contained within it are later deleted during garbage collection.
func (client Client) Delete(ctx context.Context, accountName, containerName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "Delete", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "Delete", "`containerName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, containerName)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, containerName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/get_properties.go 0000664 0000000 0000000 00000011677 14232154237 0024564 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// GetProperties returns the properties for this Container without a Lease
func (client Client) GetProperties(ctx context.Context, accountName, containerName string) (ContainerProperties, error) {
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
return client.GetPropertiesWithLeaseID(ctx, accountName, containerName, "")
}
// GetPropertiesWithLeaseID returns the properties for this Container using the specified LeaseID
func (client Client) GetPropertiesWithLeaseID(ctx context.Context, accountName, containerName, leaseID string) (result ContainerProperties, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "GetPropertiesWithLeaseID", "`containerName` cannot be an empty string.")
}
req, err := client.GetPropertiesWithLeaseIDPreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesWithLeaseIDSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesWithLeaseIDPreparer prepares the GetPropertiesWithLeaseID request.
func (client Client) GetPropertiesWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesWithLeaseIDSender sends the GetPropertiesWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesWithLeaseIDResponder handles the response to the GetPropertiesWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesWithLeaseIDResponder(resp *http.Response) (result ContainerProperties, err error) {
if resp != nil {
result.LeaseStatus = LeaseStatus(resp.Header.Get("x-ms-lease-status"))
result.LeaseState = LeaseState(resp.Header.Get("x-ms-lease-state"))
if result.LeaseStatus == Locked {
duration := LeaseDuration(resp.Header.Get("x-ms-lease-duration"))
result.LeaseDuration = &duration
}
// If this header is not returned in the response, the container is private to the account owner.
accessLevel := resp.Header.Get("x-ms-blob-public-access")
if accessLevel != "" {
result.AccessLevel = AccessLevel(accessLevel)
} else {
result.AccessLevel = Private
}
// we can't necessarily use strconv.ParseBool here since this could be nil (only in some API versions)
result.HasImmutabilityPolicy = strings.EqualFold(resp.Header.Get("x-ms-has-immutability-policy"), "true")
result.HasLegalHold = strings.EqualFold(resp.Header.Get("x-ms-has-legal-hold"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/lease_acquire.go 0000664 0000000 0000000 00000007762 14232154237 0024333 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type AcquireLeaseInput 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
LeaseDuration int
ProposedLeaseID string
}
type AcquireLeaseResponse struct {
autorest.Response
LeaseID string
}
// AcquireLease establishes and manages a lock on a container for delete operations.
func (client Client) AcquireLease(ctx context.Context, accountName, containerName string, input AcquireLeaseInput) (result AcquireLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "AcquireLease", "`containerName` cannot be an empty string.")
}
// An infinite lease duration is -1 seconds. A non-infinite lease can be between 15 and 60 seconds
if input.LeaseDuration != -1 && (input.LeaseDuration <= 15 || input.LeaseDuration >= 60) {
return result, validation.NewError("containers.Client", "AcquireLease", "`input.LeaseDuration` must be -1 (infinite), or between 15 and 60 seconds.")
}
req, err := client.AcquireLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", nil, "Failure preparing request")
return
}
resp, err := client.AcquireLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure sending request")
return
}
result, err = client.AcquireLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "AcquireLease", resp, "Failure responding to request")
return
}
return
}
// AcquireLeasePreparer prepares the AcquireLease request.
func (client Client) AcquireLeasePreparer(ctx context.Context, accountName string, containerName string, input AcquireLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "acquire",
"x-ms-lease-duration": input.LeaseDuration,
}
if input.ProposedLeaseID != "" {
headers["x-ms-proposed-lease-id"] = input.ProposedLeaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AcquireLeaseSender sends the AcquireLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AcquireLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AcquireLeaseResponder handles the response to the AcquireLease request. The method always
// closes the http.Response Body.
func (client Client) AcquireLeaseResponder(resp *http.Response) (result AcquireLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/lease_break.go 0000664 0000000 0000000 00000010521 14232154237 0023751 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strconv"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type BreakLeaseInput struct {
// For a break operation, proposed duration the lease should continue
// before it is broken, in seconds, between 0 and 60.
// This break period is only used if it is shorter than the time remaining on the lease.
// If longer, the time remaining on the lease is used.
// A new lease will not be available before the break period has expired,
// but the lease may be held for longer than the break period.
// If this header does not appear with a break operation, a fixed-duration lease breaks
// after the remaining lease period elapses, and an infinite lease breaks immediately.
BreakPeriod *int
LeaseID string
}
type BreakLeaseResponse struct {
autorest.Response
// Approximate time remaining in the lease period, in seconds.
// If the break is immediate, 0 is returned.
LeaseTime int
}
// BreakLease breaks a lock based on it's Lease ID
func (client Client) BreakLease(ctx context.Context, accountName, containerName string, input BreakLeaseInput) (result BreakLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`containerName` cannot be an empty string.")
}
if input.LeaseID == "" {
return result, validation.NewError("containers.Client", "BreakLease", "`input.LeaseID` cannot be an empty string.")
}
req, err := client.BreakLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", nil, "Failure preparing request")
return
}
resp, err := client.BreakLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure sending request")
return
}
result, err = client.BreakLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "BreakLease", resp, "Failure responding to request")
return
}
return
}
// BreakLeasePreparer prepares the BreakLease request.
func (client Client) BreakLeasePreparer(ctx context.Context, accountName string, containerName string, input BreakLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "break",
"x-ms-lease-id": input.LeaseID,
}
if input.BreakPeriod != nil {
headers["x-ms-lease-break-period"] = *input.BreakPeriod
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// BreakLeaseSender sends the BreakLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) BreakLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// BreakLeaseResponder handles the response to the BreakLease request. The method always
// closes the http.Response Body.
func (client Client) BreakLeaseResponder(resp *http.Response) (result BreakLeaseResponse, err error) {
if resp != nil {
leaseRaw := resp.Header.Get("x-ms-lease-time")
if leaseRaw != "" {
i, err := strconv.Atoi(leaseRaw)
if err == nil {
result.LeaseTime = i
}
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/lease_change.go 0000664 0000000 0000000 00000007356 14232154237 0024126 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ChangeLeaseInput struct {
ExistingLeaseID string
ProposedLeaseID string
}
type ChangeLeaseResponse struct {
autorest.Response
LeaseID string
}
// ChangeLease changes the lock from one Lease ID to another Lease ID
func (client Client) ChangeLease(ctx context.Context, accountName, containerName string, input ChangeLeaseInput) (result ChangeLeaseResponse, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`containerName` cannot be an empty string.")
}
if input.ExistingLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ExistingLeaseID` cannot be an empty string.")
}
if input.ProposedLeaseID == "" {
return result, validation.NewError("containers.Client", "ChangeLease", "`input.ProposedLeaseID` cannot be an empty string.")
}
req, err := client.ChangeLeasePreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", nil, "Failure preparing request")
return
}
resp, err := client.ChangeLeaseSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure sending request")
return
}
result, err = client.ChangeLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ChangeLease", resp, "Failure responding to request")
return
}
return
}
// ChangeLeasePreparer prepares the ChangeLease request.
func (client Client) ChangeLeasePreparer(ctx context.Context, accountName string, containerName string, input ChangeLeaseInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "change",
"x-ms-lease-id": input.ExistingLeaseID,
"x-ms-proposed-lease-id": input.ProposedLeaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ChangeLeaseSender sends the ChangeLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ChangeLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ChangeLeaseResponder handles the response to the ChangeLease request. The method always
// closes the http.Response Body.
func (client Client) ChangeLeaseResponder(resp *http.Response) (result ChangeLeaseResponse, err error) {
if resp != nil {
result.LeaseID = resp.Header.Get("x-ms-lease-id")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/lease_release.go 0000664 0000000 0000000 00000006324 14232154237 0024313 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// ReleaseLease releases the lock based on the Lease ID
func (client Client) ReleaseLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "ReleaseLease", "`leaseID` cannot be an empty string.")
}
req, err := client.ReleaseLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", nil, "Failure preparing request")
return
}
resp, err := client.ReleaseLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure sending request")
return
}
result, err = client.ReleaseLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ReleaseLease", resp, "Failure responding to request")
return
}
return
}
// ReleaseLeasePreparer prepares the ReleaseLease request.
func (client Client) ReleaseLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "release",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ReleaseLeaseSender sends the ReleaseLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ReleaseLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ReleaseLeaseResponder handles the response to the ReleaseLease request. The method always
// closes the http.Response Body.
func (client Client) ReleaseLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/lease_renew.go 0000664 0000000 0000000 00000006250 14232154237 0024011 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// RenewLease renews the lock based on the Lease ID
func (client Client) RenewLease(ctx context.Context, accountName, containerName, leaseID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`containerName` cannot be an empty string.")
}
if leaseID == "" {
return result, validation.NewError("containers.Client", "RenewLease", "`leaseID` cannot be an empty string.")
}
req, err := client.RenewLeasePreparer(ctx, accountName, containerName, leaseID)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", nil, "Failure preparing request")
return
}
resp, err := client.RenewLeaseSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure sending request")
return
}
result, err = client.RenewLeaseResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "RenewLease", resp, "Failure responding to request")
return
}
return
}
// RenewLeasePreparer prepares the RenewLease request.
func (client Client) RenewLeasePreparer(ctx context.Context, accountName string, containerName string, leaseID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "container"),
"comp": autorest.Encode("path", "lease"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-lease-action": "renew",
"x-ms-lease-id": leaseID,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// RenewLeaseSender sends the RenewLease request. The method will close the
// http.Response Body if it receives an error.
func (client Client) RenewLeaseSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// RenewLeaseResponder handles the response to the RenewLease request. The method always
// closes the http.Response Body.
func (client Client) RenewLeaseResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/lifecycle_test.go 0000664 0000000 0000000 00000013122 14232154237 0024512 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageContainer = Client{}
func TestContainerLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
containerName := fmt.Sprintf("cont-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
containersClient := NewWithEnvironment(client.Environment)
containersClient.Client = client.PrepareWithAuthorizer(containersClient.Client, storageAuth)
// first let's test an empty container
input := CreateInput{}
_, err = containersClient.Create(ctx, accountName, containerName, input)
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
container, err := containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error retrieving: %s", err))
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if len(container.MetaData) != 0 {
t.Fatalf("Expected MetaData to be empty but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the metadata
metaData := map[string]string{
"dont": "kill-my-vibe",
}
_, err = containersClient.SetMetaData(ctx, accountName, containerName, metaData)
if err != nil {
t.Fatal(fmt.Errorf("Error updating metadata: %s", err))
}
// give azure time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.MetaData["dont"] != "kill-my-vibe" {
t.Fatalf("Expected `kill-my-vibe` but got %q", container.MetaData["dont"])
}
if container.AccessLevel != Private {
t.Fatalf("Expected Access Level to be Private but got %q", container.AccessLevel)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// then update the ACL
_, err = containersClient.SetAccessControl(ctx, accountName, containerName, Blob)
if err != nil {
t.Fatal(fmt.Errorf("Error updating ACL's: %s", err))
}
// give azure some time to replicate
time.Sleep(2 * time.Second)
// then assert that
container, err = containersClient.GetProperties(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error re-retrieving: %s", err))
}
if container.AccessLevel != Blob {
t.Fatalf("Expected Access Level to be Blob but got %q", container.AccessLevel)
}
if len(container.MetaData) != 1 {
t.Fatalf("Expected 1 item in the metadata but got: %s", container.MetaData)
}
if container.LeaseStatus != Unlocked {
t.Fatalf("Expected Container Lease to be Unlocked but was: %s", container.LeaseStatus)
}
// acquire a lease for 30s
acquireLeaseInput := AcquireLeaseInput{
LeaseDuration: 30,
}
acquireLeaseResp, err := containersClient.AcquireLease(ctx, accountName, containerName, acquireLeaseInput)
if err != nil {
t.Fatalf("Error acquiring lease: %s", err)
}
t.Logf("[DEBUG] Lease ID: %s", acquireLeaseResp.LeaseID)
// we should then be able to update the ID
t.Logf("[DEBUG] Changing lease..")
updateLeaseInput := ChangeLeaseInput{
ExistingLeaseID: acquireLeaseResp.LeaseID,
ProposedLeaseID: "aaaabbbb-aaaa-bbbb-cccc-aaaabbbbcccc",
}
updateLeaseResp, err := containersClient.ChangeLease(ctx, accountName, containerName, updateLeaseInput)
if err != nil {
t.Fatalf("Error changing lease: %s", err)
}
// then renew it
_, err = containersClient.RenewLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error renewing lease: %s", err)
}
// and then give it a timeout
breakPeriod := 20
breakLeaseInput := BreakLeaseInput{
LeaseID: updateLeaseResp.LeaseID,
BreakPeriod: &breakPeriod,
}
breakLeaseResp, err := containersClient.BreakLease(ctx, accountName, containerName, breakLeaseInput)
if err != nil {
t.Fatalf("Error breaking lease: %s", err)
}
if breakLeaseResp.LeaseTime == 0 {
t.Fatalf("Lease broke immediately when should have waited: %d", breakLeaseResp.LeaseTime)
}
// and finally ditch it
_, err = containersClient.ReleaseLease(ctx, accountName, containerName, updateLeaseResp.LeaseID)
if err != nil {
t.Fatalf("Error releasing lease: %s", err)
}
t.Logf("[DEBUG] Listing blobs in the container..")
listInput := ListBlobsInput{}
listResult, err := containersClient.ListBlobs(ctx, accountName, containerName, listInput)
if err != nil {
t.Fatalf("Error listing blobs: %s", err)
}
if len(listResult.Blobs.Blobs) != 0 {
t.Fatalf("Expected there to be no blobs in the container but got %d", len(listResult.Blobs.Blobs))
}
t.Logf("[DEBUG] Deleting..")
_, err = containersClient.Delete(ctx, accountName, containerName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/list_blobs.go 0000664 0000000 0000000 00000015033 14232154237 0023653 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListBlobsInput struct {
Delimiter *string
Include *[]Dataset
Marker *string
MaxResults *int
Prefix *string
}
type ListBlobsResult struct {
autorest.Response
Delimiter string `xml:"Delimiter"`
Marker string `xml:"Marker"`
MaxResults int `xml:"MaxResults"`
NextMarker *string `xml:"NextMarker,omitempty"`
Prefix string `xml:"Prefix"`
Blobs Blobs `xml:"Blobs"`
}
type Blobs struct {
Blobs []BlobDetails `xml:"Blob"`
BlobPrefix *BlobPrefix `xml:"BlobPrefix"`
}
type BlobDetails struct {
Name string `xml:"Name"`
Deleted bool `xml:"Deleted,omitempty"`
MetaData map[string]interface{} `map:"Metadata,omitempty"`
Properties *BlobProperties `xml:"Properties,omitempty"`
Snapshot *string `xml:"Snapshot,omitempty"`
}
type BlobProperties struct {
AccessTier *string `xml:"AccessTier,omitempty"`
AccessTierInferred *bool `xml:"AccessTierInferred,omitempty"`
AccessTierChangeTime *string `xml:"AccessTierChangeTime,omitempty"`
BlobType *string `xml:"BlobType,omitempty"`
BlobSequenceNumber *string `xml:"x-ms-blob-sequence-number,omitempty"`
CacheControl *string `xml:"Cache-Control,omitempty"`
ContentEncoding *string `xml:"ContentEncoding,omitempty"`
ContentLanguage *string `xml:"Content-Language,omitempty"`
ContentLength *int64 `xml:"Content-Length,omitempty"`
ContentMD5 *string `xml:"Content-MD5,omitempty"`
ContentType *string `xml:"Content-Type,omitempty"`
CopyCompletionTime *string `xml:"CopyCompletionTime,omitempty"`
CopyId *string `xml:"CopyId,omitempty"`
CopyStatus *string `xml:"CopyStatus,omitempty"`
CopySource *string `xml:"CopySource,omitempty"`
CopyProgress *string `xml:"CopyProgress,omitempty"`
CopyStatusDescription *string `xml:"CopyStatusDescription,omitempty"`
CreationTime *string `xml:"CreationTime,omitempty"`
ETag *string `xml:"Etag,omitempty"`
DeletedTime *string `xml:"DeletedTime,omitempty"`
IncrementalCopy *bool `xml:"IncrementalCopy,omitempty"`
LastModified *string `xml:"Last-Modified,omitempty"`
LeaseDuration *string `xml:"LeaseDuration,omitempty"`
LeaseState *string `xml:"LeaseState,omitempty"`
LeaseStatus *string `xml:"LeaseStatus,omitempty"`
RemainingRetentionDays *string `xml:"RemainingRetentionDays,omitempty"`
ServerEncrypted *bool `xml:"ServerEncrypted,omitempty"`
}
type BlobPrefix struct {
Name string `xml:"Name"`
}
// ListBlobs lists the blobs matching the specified query within the specified Container
func (client Client) ListBlobs(ctx context.Context, accountName, containerName string, input ListBlobsInput) (result ListBlobsResult, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "ListBlobs", "`containerName` cannot be an empty string.")
}
if input.MaxResults != nil && (*input.MaxResults <= 0 || *input.MaxResults > 5000) {
return result, validation.NewError("containers.Client", "ListBlobs", "`input.MaxResults` can either be nil or between 0 and 5000.")
}
req, err := client.ListBlobsPreparer(ctx, accountName, containerName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", nil, "Failure preparing request")
return
}
resp, err := client.ListBlobsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure sending request")
return
}
result, err = client.ListBlobsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "ListBlobs", resp, "Failure responding to request")
return
}
return
}
// ListBlobsPreparer prepares the ListBlobs request.
func (client Client) ListBlobsPreparer(ctx context.Context, accountName, containerName string, input ListBlobsInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "list"),
"restype": autorest.Encode("query", "container"),
}
if input.Delimiter != nil {
queryParameters["delimiter"] = autorest.Encode("query", *input.Delimiter)
}
if input.Include != nil {
vals := make([]string, 0)
for _, v := range *input.Include {
vals = append(vals, string(v))
}
include := strings.Join(vals, ",")
queryParameters["include"] = autorest.Encode("query", include)
}
if input.Marker != nil {
queryParameters["marker"] = autorest.Encode("query", *input.Marker)
}
if input.MaxResults != nil {
queryParameters["maxresults"] = autorest.Encode("query", *input.MaxResults)
}
if input.Prefix != nil {
queryParameters["prefix"] = autorest.Encode("query", *input.Prefix)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListBlobsSender sends the ListBlobs request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListBlobsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListBlobsResponder handles the response to the ListBlobs request. The method always
// closes the http.Response Body.
func (client Client) ListBlobsResponder(resp *http.Response) (result ListBlobsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/models.go 0000664 0000000 0000000 00000003464 14232154237 0023007 0 ustar 00root root 0000000 0000000 package containers
import "github.com/Azure/go-autorest/autorest"
type AccessLevel string
var (
// Blob specifies public read access for blobs.
// Blob data within this container can be read via anonymous request,
// but container data is not available.
// Clients cannot enumerate blobs within the container via anonymous request.
Blob AccessLevel = "blob"
// Container specifies full public read access for container and blob data.
// Clients can enumerate blobs within the container via anonymous request,
// but cannot enumerate containers within the storage account.
Container AccessLevel = "container"
// Private specifies that container data is private to the account owner
Private AccessLevel = ""
)
type ContainerProperties struct {
autorest.Response
AccessLevel AccessLevel
LeaseStatus LeaseStatus
LeaseState LeaseState
LeaseDuration *LeaseDuration
MetaData map[string]string
HasImmutabilityPolicy bool
HasLegalHold bool
}
type Dataset string
var (
Copy Dataset = "copy"
Deleted Dataset = "deleted"
MetaData Dataset = "metadata"
Snapshots Dataset = "snapshots"
UncommittedBlobs Dataset = "uncommittedblobs"
)
type ErrorResponse struct {
Code *string `xml:"Code"`
Message *string `xml:"Message"`
}
type LeaseDuration string
var (
// If this lease is for a Fixed Duration
Fixed LeaseDuration = "fixed"
// If this lease is for an Indefinite Duration
Infinite LeaseDuration = "infinite"
)
type LeaseState string
var (
Available LeaseState = "available"
Breaking LeaseState = "breaking"
Broken LeaseState = "broken"
Expired LeaseState = "expired"
Leased LeaseState = "leased"
)
type LeaseStatus string
var (
Locked LeaseStatus = "locked"
Unlocked LeaseStatus = "unlocked"
)
giovanni-0.20.0/storage/2020-08-04/blob/containers/resource_id.go 0000664 0000000 0000000 00000003260 14232154237 0024021 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Container
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, containerName string) string {
domain := endpoints.GetBlobEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, containerName)
}
// GetResourceManagerResourceID returns the Resource Manager specific
// ResourceID for a specific Storage Container
func (client Client) GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, containerName string) string {
fmtStr := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/%s/blobServices/default/containers/%s"
return fmt.Sprintf(fmtStr, subscriptionID, resourceGroup, accountName, containerName)
}
type ResourceID struct {
AccountName string
ContainerName string
}
// ParseResourceID parses the Resource ID and returns an object which can be used
// to interact with the Container Resource
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.blob.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
containerName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ContainerName: containerName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/resource_id_test.go 0000664 0000000 0000000 00000006654 14232154237 0025072 0 ustar 00root root 0000000 0000000 package containers
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestGetResourceManagerResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.GermanCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.PublicCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/blobServices/default/containers/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceManagerResourceID("11112222-3333-4444-5555-666677778888", "group1", "account1", "container1")
if actual != v.Expected {
t.Fatalf("Expected the Resource Manager Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.blob.core.chinacloudapi.cn/container1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.blob.core.cloudapi.de/container1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.blob.core.windows.net/container1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.blob.core.usgovcloudapi.net/container1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ContainerName != "container1" {
t.Fatalf("Expected the container name to be `container1` but got %q", actual.ContainerName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/set_acl.go 0000664 0000000 0000000 00000007651 14232154237 0023140 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetAccessControl sets the Access Control for a Container without a Lease ID
func (client Client) SetAccessControl(ctx context.Context, accountName, containerName string, level AccessLevel) (autorest.Response, error) {
return client.SetAccessControlWithLeaseID(ctx, accountName, containerName, "", level)
}
// SetAccessControlWithLeaseID sets the Access Control for a Container using the specified Lease ID
func (client Client) SetAccessControlWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetAccessControl", "`containerName` cannot be an empty string.")
}
req, err := client.SetAccessControlWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, level)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetAccessControl", resp, "Failure responding to request")
return
}
return
}
// SetAccessControlWithLeaseIDPreparer prepares the SetAccessControlWithLeaseID request.
func (client Client) SetAccessControlWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, level AccessLevel) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "acl"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = client.setAccessLevelIntoHeaders(headers, level)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlWithLeaseIDSender sends the SetAccessControlWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlWithLeaseIDResponder handles the response to the SetAccessControlWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/set_metadata.go 0000664 0000000 0000000 00000010137 14232154237 0024152 0 ustar 00root root 0000000 0000000 package containers
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the specified MetaData on the Container without a Lease ID
func (client Client) SetMetaData(ctx context.Context, accountName, containerName string, metaData map[string]string) (autorest.Response, error) {
return client.SetMetaDataWithLeaseID(ctx, accountName, containerName, "", metaData)
}
// SetMetaDataWithLeaseID sets the specified MetaData on the Container using the specified Lease ID
func (client Client) SetMetaDataWithLeaseID(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if containerName == "" {
return result, validation.NewError("containers.Client", "SetMetaData", "`containerName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("containers.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataWithLeaseIDPreparer(ctx, accountName, containerName, leaseID, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataWithLeaseIDSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataWithLeaseIDResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "containers.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataWithLeaseIDPreparer prepares the SetMetaDataWithLeaseID request.
func (client Client) SetMetaDataWithLeaseIDPreparer(ctx context.Context, accountName, containerName, leaseID string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"containerName": autorest.Encode("path", containerName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
"restype": autorest.Encode("path", "container"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
// If specified, Get Container Properties only succeeds if the container’s lease is active and matches this ID.
// If there is no active lease or the ID does not match, 412 (Precondition Failed) is returned.
if leaseID != "" {
headers["x-ms-lease-id"] = leaseID
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{containerName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataWithLeaseIDSender sends the SetMetaDataWithLeaseID request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataWithLeaseIDSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataWithLeaseIDResponder handles the response to the SetMetaDataWithLeaseID request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataWithLeaseIDResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/blob/containers/version.go 0000664 0000000 0000000 00000000470 14232154237 0023203 0 ustar 00root root 0000000 0000000 package containers
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/ 0000775 0000000 0000000 00000000000 14232154237 0020726 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/ 0000775 0000000 0000000 00000000000 14232154237 0023275 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/README.md 0000664 0000000 0000000 00000004413 14232154237 0024556 0 ustar 00root root 0000000 0000000 ## Data Lake Storage Gen2 File Systems SDK for API version 2020-08-04
This package allows you to interact with the Data Lake Storage Gen2 File Systems API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
### Example Usage
```go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/go-azure-helpers/authentication"
"github.com/hashicorp/go-azure-helpers/sender"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/datalakestore/filesystems"
)
func Example() error {
accountName := "storageaccount1"
fileSystemName := "filesystem1"
builder := &authentication.Builder{
SubscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"),
ClientID: os.Getenv("ARM_CLIENT_ID"),
ClientSecret: os.Getenv("ARM_CLIENT_SECRET"),
TenantID: os.Getenv("ARM_TENANT_ID"),
Environment: os.Getenv("ARM_ENVIRONMENT"),
// Feature Toggles
SupportsClientSecretAuth: true,
}
c, err := builder.Build()
if err != nil {
return fmt.Errorf("Error building AzureRM Client: %s", err)
}
env, err := authentication.DetermineEnvironment(c.Environment)
if err != nil {
return err
}
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, c.TenantID)
if err != nil {
return err
}
// OAuthConfigForTenant returns a pointer, which can be nil.
if oauthConfig == nil {
return fmt.Errorf("Unable to configure OAuthConfig for tenant %s", c.TenantID)
}
sender := sender.BuildSender("AzureRM")
ctx := context.Background()
storageAuth, err := config.GetAuthorizationToken(sender, oauthConfig, "https://storage.azure.com/")
if err != nil {
return fmt.Errorf("Error retrieving Authorization Token")
}
fileSystemsClient := filesystems.NewWithEnvironment(env)
fileSystemsClient.Client.Authorizer = storageAuth
input := filesystems.CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
return fmt.Errorf("Error creating: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/client.go 0000664 0000000 0000000 00000001216 14232154237 0025102 0 ustar 00root root 0000000 0000000 package filesystems
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Data Lake Storage FileSystem
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Data Lake Storage FileSystem client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Data Lake Storage FileSystem client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/create.go 0000664 0000000 0000000 00000006425 14232154237 0025076 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type CreateInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
}
// Create creates a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Create(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`fileSystemName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure responding to request")
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, fileSystemName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/create_test.go 0000664 0000000 0000000 00000003202 14232154237 0026123 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCreateHasNoTagsByDefault(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 0 {
t.Fatalf("Expected 0 properties by default but got %d", len(props.Properties))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/delete.go 0000664 0000000 0000000 00000005514 14232154237 0025073 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Delete(ctx context.Context, accountName string, fileSystemName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`fileSystemName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure responding to request")
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/helpers.go 0000664 0000000 0000000 00000002041 14232154237 0025263 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"strings"
)
func buildProperties(input map[string]string) string {
// properties has to be a comma-separated key-value pair
properties := make([]string, 0)
for k, v := range input {
properties = append(properties, fmt.Sprintf("%s=%s", k, v))
}
return strings.Join(properties, ",")
}
func parseProperties(input string) (*map[string]string, error) {
properties := make(map[string]string)
if input == "" {
return &properties, nil
}
// properties is a comma-separated list of key-value pairs
splitProperties := strings.Split(input, ",")
for _, propertyRaw := range splitProperties {
// because these are base64-encoded they're likely to end in at least one =
// as such we can't string split on that -_-
position := strings.Index(propertyRaw, "=")
if position < 0 {
return nil, fmt.Errorf("Expected there to be an equals in the key value pair: %q", propertyRaw)
}
key := propertyRaw[0:position]
value := propertyRaw[position+1:]
properties[key] = value
}
return &properties, nil
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/helpers_test.go 0000664 0000000 0000000 00000002724 14232154237 0026332 0 ustar 00root root 0000000 0000000 package filesystems
import (
"reflect"
"testing"
)
func TestParseProperties(t *testing.T) {
testData := []struct {
name string
input string
expected map[string]string
expectError bool
}{
{
name: "no items",
input: "",
expected: map[string]string{},
expectError: false,
},
{
name: "invalid item",
input: "hello",
expectError: true,
},
{
name: "single item",
input: "hello=world",
expected: map[string]string{
"hello": "world",
},
},
{
name: "single-item-base64",
input: "hello=aGVsbG8=",
expected: map[string]string{
"hello": "aGVsbG8=",
},
expectError: false,
},
{
name: "single-item-base64-multipleequals",
input: "hello=d29uZGVybGFuZA==",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
},
expectError: false,
},
{
name: "multiple-items-base64",
input: "hello=d29uZGVybGFuZA==,private=ZXll",
expected: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
expectError: false,
},
}
for _, testCase := range testData {
t.Logf("[DEBUG] Test %q", testCase.name)
actual, err := parseProperties(testCase.input)
if err != nil {
if testCase.expectError {
continue
}
t.Fatalf("[DEBUG] Didn't expect an error but got %s", err)
}
if !reflect.DeepEqual(testCase.expected, *actual) {
t.Fatalf("Expected %+v but got %+v", testCase.expected, *actual)
}
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/lifecycle_test.go 0000664 0000000 0000000 00000005302 14232154237 0026622 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
if _, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
input := CreateInput{
Properties: map[string]string{
"hello": "aGVsbG8=",
},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Retrieving the Properties..")
props, err := fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 1 {
t.Fatalf("Expected 1 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "aGVsbG8=" {
t.Fatalf("Expected `hello` to be `aGVsbG8=` but got %q", props.Properties["hello"])
}
t.Logf("[DEBUG] Updating the properties..")
setInput := SetPropertiesInput{
Properties: map[string]string{
"hello": "d29uZGVybGFuZA==",
"private": "ZXll",
},
}
if _, err := fileSystemsClient.SetProperties(ctx, accountName, fileSystemName, setInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving the Properties..")
props, err = fileSystemsClient.GetProperties(ctx, accountName, fileSystemName)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
if len(props.Properties) != 2 {
t.Fatalf("Expected 2 properties by default but got %d", len(props.Properties))
}
if props.Properties["hello"] != "d29uZGVybGFuZA==" {
t.Fatalf("Expected `hello` to be `d29uZGVybGFuZA==` but got %q", props.Properties["hello"])
}
if props.Properties["private"] != "ZXll" {
t.Fatalf("Expected `private` to be `ZXll` but got %q", props.Properties["private"])
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/properties_get.go 0000664 0000000 0000000 00000007435 14232154237 0026670 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPropertiesResponse struct {
autorest.Response
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Is Hierarchical Namespace Enabled?
NamespaceEnabled bool
}
// GetProperties gets the properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) GetProperties(ctx context.Context, accountName string, fileSystemName string) (result GetPropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, fileSystemName)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure responding to request")
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResponse, err error) {
if resp != nil && resp.Header != nil {
propertiesRaw := resp.Header.Get("x-ms-properties")
var properties *map[string]string
properties, err = parseProperties(propertiesRaw)
if err != nil {
return
}
result.Properties = *properties
result.NamespaceEnabled = strings.EqualFold(resp.Header.Get("x-ms-namespace-enabled"), "tru")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/properties_set.go 0000664 0000000 0000000 00000007773 14232154237 0026711 0 ustar 00root root 0000000 0000000 package filesystems
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetPropertiesInput struct {
// A map of base64-encoded strings to store as user-defined properties with the File System
// Note that items may only contain ASCII characters in the ISO-8859-1 character set.
// This automatically gets converted to a comma-separated list of name and
// value pairs before sending to the API
Properties map[string]string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has been modified since the specified date and time.
IfModifiedSince *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has not been modified since the specified date and time.
IfUnmodifiedSince *string
}
// SetProperties sets the Properties for a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) SetProperties(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "SetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, fileSystemName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetProperties", resp, "Failure responding to request")
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string, input SetPropertiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", "filesystem"),
}
headers := map[string]interface{}{
"x-ms-properties": buildProperties(input.Properties),
"x-ms-version": APIVersion,
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
preparer := autorest.CreatePreparer(
autorest.AsPatch(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/resource_id.go 0000664 0000000 0000000 00000002417 14232154237 0026133 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Data Lake Storage FileSystem
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
type ResourceID struct {
AccountName string
DirectoryName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Data Lake Storage FileSystem API's
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.dfs.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
directoryName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/resource_id_test.go 0000664 0000000 0000000 00000003756 14232154237 0027201 0 ustar 00root root 0000000 0000000 package filesystems
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.dfs.core.chinacloudapi.cn/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.dfs.core.cloudapi.de/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.dfs.core.windows.net/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.dfs.core.usgovcloudapi.net/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected the directory name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/filesystems/version.go 0000664 0000000 0000000 00000000471 14232154237 0025313 0 ustar 00root root 0000000 0000000 package filesystems
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/ 0000775 0000000 0000000 00000000000 14232154237 0022045 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/client.go 0000664 0000000 0000000 00000001166 14232154237 0023656 0 ustar 00root root 0000000 0000000 package paths
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Data Lake Storage Path
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Data Lake Storage Path client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Data Lake Storage Path client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/create.go 0000664 0000000 0000000 00000006170 14232154237 0023643 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PathResource string
const PathResourceFile PathResource = "file"
const PathResourceDirectory PathResource = "directory"
type CreateInput struct {
Resource PathResource
}
// Create creates a Data Lake Store Gen2 Path within a Storage Account
func (client Client) Create(ctx context.Context, accountName string, fileSystemName string, path string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Create", "`fileSystemName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, fileSystemName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Create", resp, "Failure responding to request")
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, fileSystemName string, path string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"resource": autorest.Encode("query", input.Resource),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/create_test.go 0000664 0000000 0000000 00000003512 14232154237 0024677 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/datalakestore/filesystems"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestCreateDirectory(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
path := "test"
if _, err = client.BuildTestResourcesWithHns(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := filesystems.NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
fileSystemInput := filesystems.CreateInput{
Properties: map[string]string{},
}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, fileSystemInput); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Creating path..")
pathsClient := NewWithEnvironment(client.Environment)
pathsClient.Client = client.PrepareWithStorageResourceManagerAuth(pathsClient.Client)
input := CreateInput{
Resource: PathResourceDirectory,
}
if _, err = pathsClient.Create(ctx, accountName, fileSystemName, path, input); err != nil {
t.Fatal(fmt.Errorf("Error creating path: %s", err))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/delete.go 0000664 0000000 0000000 00000005403 14232154237 0023640 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a Data Lake Store Gen2 FileSystem within a Storage Account
func (client Client) Delete(ctx context.Context, accountName string, fileSystemName string, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "Delete", "`fileSystemName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, fileSystemName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "Delete", resp, "Failure responding to request")
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, fileSystemName string, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/helpers.go 0000664 0000000 0000000 00000000431 14232154237 0024034 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
)
func parsePathResource(input string) (PathResource, error) {
switch input {
case "file":
return PathResourceFile, nil
case "directory":
return PathResourceDirectory, nil
}
return "", fmt.Errorf("Unhandled path resource type %q", input)
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/lifecycle_test.go 0000664 0000000 0000000 00000007307 14232154237 0025401 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/datalakestore/filesystems"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestLifecycle(t *testing.T) {
const defaultACLString = "user::rwx,group::r-x,other::---"
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
fileSystemName := fmt.Sprintf("acctestfs-%s", testhelpers.RandomString())
path := "test"
if _, err = client.BuildTestResourcesWithHns(ctx, resourceGroup, accountName, storage.KindBlobStorage); err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
fileSystemsClient := filesystems.NewWithEnvironment(client.Environment)
fileSystemsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
pathsClient := NewWithEnvironment(client.Environment)
pathsClient.Client = client.PrepareWithStorageResourceManagerAuth(fileSystemsClient.Client)
t.Logf("[DEBUG] Creating an empty File System..")
fileSystemInput := filesystems.CreateInput{}
if _, err = fileSystemsClient.Create(ctx, accountName, fileSystemName, fileSystemInput); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Creating folder 'test' ..")
input := CreateInput{
Resource: PathResourceDirectory,
}
if _, err = pathsClient.Create(ctx, accountName, fileSystemName, path, input); err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' ..")
props, err := pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties: %s", err))
}
t.Logf("[DEBUG] Props.Owner: %q", props.Owner)
t.Logf("[DEBUG] Props.Group: %q", props.Group)
t.Logf("[DEBUG] Props.ACL: %q", props.ACL)
t.Logf("[DEBUG] Props.ETag: %q", props.ETag)
t.Logf("[DEBUG] Props.LastModified: %q", props.LastModified)
if props.ACL != defaultACLString {
t.Fatal(fmt.Errorf("Expected Default ACL %q, got %q", defaultACLString, props.ACL))
}
newACL := "user::rwx,group::r-x,other::r-x,default:user::rwx,default:group::r-x,default:other::---"
accessControlInput := SetAccessControlInput{
ACL: &newACL,
}
t.Logf("[DEBUG] Setting Access Control for folder 'test' ..")
if _, err = pathsClient.SetAccessControl(ctx, accountName, fileSystemName, path, accessControlInput); err != nil {
t.Fatal(fmt.Errorf("Error setting Access Control %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' (2) ..")
props, err = pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err != nil {
t.Fatal(fmt.Errorf("Error getting properties (2): %s", err))
}
if props.ACL != newACL {
t.Fatal(fmt.Errorf("Expected new ACL %q, got %q", newACL, props.ACL))
}
t.Logf("[DEBUG] Deleting path 'test' ..")
if _, err = pathsClient.Delete(ctx, accountName, fileSystemName, path); err != nil {
t.Fatal(fmt.Errorf("Error deleting path: %s", err))
}
t.Logf("[DEBUG] Getting properties for folder 'test' (3) ..")
props, err = pathsClient.GetProperties(ctx, accountName, fileSystemName, path, GetPropertiesActionGetAccessControl)
if err == nil {
t.Fatal(fmt.Errorf("Didn't get error getting properties after deleting path (3)"))
}
t.Logf("[DEBUG] Deleting File System..")
if _, err := fileSystemsClient.Delete(ctx, accountName, fileSystemName); err != nil {
t.Fatalf("Error deleting filesystem: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/properties_get.go 0000664 0000000 0000000 00000010721 14232154237 0025430 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetPropertiesResponse struct {
autorest.Response
ETag string
LastModified time.Time
// ResourceType is only returned for GetPropertiesActionGetStatus requests
ResourceType PathResource
Owner string
Group string
// ACL is only returned for GetPropertiesActionGetAccessControl requests
ACL string
}
type GetPropertiesAction string
const (
GetPropertiesActionGetStatus GetPropertiesAction = "getStatus"
GetPropertiesActionGetAccessControl GetPropertiesAction = "getAccessControl"
)
// GetProperties gets the properties for a Data Lake Store Gen2 Path in a FileSystem within a Storage Account
func (client Client) GetProperties(ctx context.Context, accountName string, fileSystemName string, path string, action GetPropertiesAction) (result GetPropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "GetProperties", "`fileSystemName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, fileSystemName, path, action)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "GetProperties", resp, "Failure responding to request")
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName string, fileSystemName string, path string, action GetPropertiesAction) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"action": autorest.Encode("query", string(action)),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResponse, err error) {
result = GetPropertiesResponse{}
if resp != nil && resp.Header != nil {
resourceTypeRaw := resp.Header.Get("x-ms-resource-type")
var resourceType PathResource
if resourceTypeRaw != "" {
resourceType, err = parsePathResource(resourceTypeRaw)
if err != nil {
return GetPropertiesResponse{}, err
}
result.ResourceType = resourceType
}
result.ETag = resp.Header.Get("ETag")
if lastModifiedRaw := resp.Header.Get("Last-Modified"); lastModifiedRaw != "" {
lastModified, err := time.Parse(time.RFC1123, lastModifiedRaw)
if err != nil {
return GetPropertiesResponse{}, err
}
result.LastModified = lastModified
}
result.Owner = resp.Header.Get("x-ms-owner")
result.Group = resp.Header.Get("x-ms-group")
result.ACL = resp.Header.Get("x-ms-acl")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return result, err
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/properties_set.go 0000664 0000000 0000000 00000010024 14232154237 0025440 0 ustar 00root root 0000000 0000000 package paths
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type SetAccessControlInput struct {
Owner *string
Group *string
ACL *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has been modified since the specified date and time.
IfModifiedSince *string
// Optional - A date and time value.
// Specify this header to perform the operation only if the resource has not been modified since the specified date and time.
IfUnmodifiedSince *string
}
// SetProperties sets the access control properties for a Data Lake Store Gen2 Path within a Storage Account File System
func (client Client) SetAccessControl(ctx context.Context, accountName string, fileSystemName string, path string, input SetAccessControlInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("datalakestore.Client", "SetAccessControl", "`accountName` cannot be an empty string.")
}
if fileSystemName == "" {
return result, validation.NewError("datalakestore.Client", "SetAccessControl", "`fileSystemName` cannot be an empty string.")
}
req, err := client.SetAccessControlPreparer(ctx, accountName, fileSystemName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", nil, "Failure preparing request")
return
}
resp, err := client.SetAccessControlSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", resp, "Failure sending request")
return
}
result, err = client.SetAccessControlResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "datalakestore.Client", "SetAccessControl", resp, "Failure responding to request")
}
return
}
// SetAccessControlPreparer prepares the SetAccessControl request.
func (client Client) SetAccessControlPreparer(ctx context.Context, accountName string, fileSystemName string, path string, input SetAccessControlInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"fileSystemName": autorest.Encode("path", fileSystemName),
"path": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"action": autorest.Encode("query", "setAccessControl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if input.Owner != nil {
headers["x-ms-owner"] = *input.Owner
}
if input.Group != nil {
headers["x-ms-group"] = *input.Group
}
if input.ACL != nil {
headers["x-ms-acl"] = *input.ACL
}
if input.IfModifiedSince != nil {
headers["If-Modified-Since"] = *input.IfModifiedSince
}
if input.IfUnmodifiedSince != nil {
headers["If-Unmodified-Since"] = *input.IfUnmodifiedSince
}
preparer := autorest.CreatePreparer(
autorest.AsPatch(),
autorest.WithBaseURL(endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{fileSystemName}/{path}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetAccessControlSender sends the SetAccessControl request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetAccessControlSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetAccessControlResponder handles the response to the SetAccessControl request. The method always
// closes the http.Response Body.
func (client Client) SetAccessControlResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/resource_id.go 0000664 0000000 0000000 00000003140 14232154237 0024675 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Data Lake Storage FileSystem
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, fileSystemName, path string) string {
domain := endpoints.GetDataLakeStoreEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, fileSystemName, path)
}
type ResourceID struct {
AccountName string
FileSystemName string
Path string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Data Lake Storage FileSystem API's
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.dfs.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
fileSystemAndPath := strings.TrimPrefix(uri.Path, "/")
separatorIndex := strings.Index(fileSystemAndPath, "/")
var fileSystem, path string
if separatorIndex < 0 {
fileSystem = fileSystemAndPath
path = ""
} else {
fileSystem = fileSystemAndPath[0:separatorIndex]
path = fileSystemAndPath[separatorIndex+1:]
}
return &ResourceID{
AccountName: *accountName,
FileSystemName: fileSystem,
Path: path,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/resource_id_test.go 0000664 0000000 0000000 00000004353 14232154237 0025743 0 ustar 00root root 0000000 0000000 package paths
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
AccountName string
FileSystemName string
Path string
Expected string
}{
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "test",
Expected: "https://account1.dfs.core.windows.net/fs1/test",
},
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "test/test2",
Expected: "https://account1.dfs.core.windows.net/fs1/test/test2",
},
{
AccountName: "account1",
FileSystemName: "fs1",
Path: "",
Expected: "https://account1.dfs.core.windows.net/fs1/",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Path %q", v.Path)
c := NewWithEnvironment(azure.PublicCloud)
actual := c.GetResourceID(v.AccountName, v.FileSystemName, v.Path)
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Input string
AccountName string
FileSystemName string
Path string
}{
{
Input: "https://account1.dfs.core.windows.net/fs1/test",
AccountName: "account1",
FileSystemName: "fs1",
Path: "test",
},
{
Input: "https://account1.dfs.core.windows.net/fs1/test/test2",
AccountName: "account1",
FileSystemName: "fs1",
Path: "test/test2",
},
{
Input: "https://account1.dfs.core.windows.net/fs1/",
AccountName: "account1",
FileSystemName: "fs1",
Path: "",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Path %q", v.Path)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != v.AccountName {
t.Fatalf("Expected the account name to be `%q` but got %q", v.AccountName, actual.AccountName)
}
if actual.FileSystemName != v.FileSystemName {
t.Fatalf("Expected the file system name to be `%q` but got %q", v.FileSystemName, actual.FileSystemName)
}
if actual.Path != v.Path {
t.Fatalf("Expected the path to be `%q` but got %q", v.Path, actual.Path)
}
}
}
giovanni-0.20.0/storage/2020-08-04/datalakestore/paths/version.go 0000664 0000000 0000000 00000000463 14232154237 0024064 0 ustar 00root root 0000000 0000000 package paths
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/file/ 0000775 0000000 0000000 00000000000 14232154237 0017022 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/file/directories/ 0000775 0000000 0000000 00000000000 14232154237 0021336 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/file/directories/README.md 0000664 0000000 0000000 00000002364 14232154237 0022622 0 ustar 00root root 0000000 0000000 ## File Storage Directories SDK for API version 2020-08-04
This package allows you to interact with the Directories File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Limitations
* At this time the headers `x-ms-file-permission` and `x-ms-file-attributes` are hard-coded (to `inherit` and `None`, respectively).
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/directories"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
directoriesClient := directories.New()
directoriesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := directoriesClient.Create(ctx, accountName, shareName, directoryName, metadata); err != nil {
return fmt.Errorf("Error creating Directory: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/file/directories/api.go 0000664 0000000 0000000 00000001375 14232154237 0022444 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageDirectory interface {
Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error)
SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName, path string, input CreateDirectoryInput) (result autorest.Response, err error)
GetResourceID(accountName, shareName, directoryName string) string
Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error)
}
giovanni-0.20.0/storage/2020-08-04/file/directories/client.go 0000664 0000000 0000000 00000001132 14232154237 0023140 0 ustar 00root root 0000000 0000000 package directories
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/file/directories/create.go 0000664 0000000 0000000 00000011273 14232154237 0023134 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateDirectoryInput struct {
// The time at which this file was created at - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-creation-time` field.
// ... Yes I know it says File not Directory, I didn't design the API.
CreatedAt *time.Time
// The time at which this file was last modified - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-last-write-time` field.
// ... Yes I know it says File not Directory, I didn't design the API.
LastModified *time.Time
// MetaData is a mapping of key value pairs which should be assigned to this directory
MetaData map[string]string
}
// Create creates a new directory under the specified share or parent directory.
func (client Client) Create(ctx context.Context, accountName, shareName, path string, input CreateDirectoryInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Create", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Create", "`path` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("directories.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, input)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path string, input CreateDirectoryInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
var coalesceDate = func(input *time.Time, defaultVal string) string {
if input == nil {
return defaultVal
}
return input.Format(time.RFC1123)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// ... Yes I know these say File not Directory, I didn't design the API.
"x-ms-file-permission": "inherit", // TODO: expose this in future
"x-ms-file-attributes": "None", // TODO: expose this in future
"x-ms-file-creation-time": coalesceDate(input.CreatedAt, "now"),
"x-ms-file-last-write-time": coalesceDate(input.LastModified, "now"),
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/directories/delete.go 0000664 0000000 0000000 00000006343 14232154237 0023135 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete removes the specified empty directory
// Note that the directory must be empty before it can be deleted.
func (client Client) Delete(ctx context.Context, accountName, shareName, path string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Delete", "`path` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/directories/get.go 0000664 0000000 0000000 00000007432 14232154237 0022452 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
// A set of name-value pairs that contain metadata for the directory.
MetaData map[string]string
// The value of this header is set to true if the directory metadata is completely
// encrypted using the specified algorithm. Otherwise, the value is set to false.
DirectoryMetaDataEncrypted bool
}
// Get returns all system properties for the specified directory,
// and can also be used to check the existence of a directory.
func (client Client) Get(ctx context.Context, accountName, shareName, path string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "Get", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "Get", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "Get", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "Get", "`path` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
result.DirectoryMetaDataEncrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/directories/lifecycle_test.go 0000664 0000000 0000000 00000007447 14232154237 0024677 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var StorageFile = Client{}
func TestDirectoriesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
directoriesClient := NewWithEnvironment(client.Environment)
directoriesClient.Client = client.PrepareWithAuthorizer(directoriesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, true)
metaData := map[string]string{
"hello": "world",
}
log.Printf("[DEBUG] Creating Top Level..")
createInput := CreateDirectoryInput{
MetaData: metaData,
}
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello", createInput); err != nil {
t.Fatalf("Error creating Top Level Directory: %s", err)
}
log.Printf("[DEBUG] Creating Inner..")
if _, err := directoriesClient.Create(ctx, accountName, shareName, "hello/there", createInput); err != nil {
t.Fatalf("Error creating Inner Directory: %s", err)
}
log.Printf("[DEBUG] Retrieving share")
innerDir, err := directoriesClient.Get(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving Inner Directory: %s", err)
}
if innerDir.DirectoryMetaDataEncrypted != true {
t.Fatalf("Expected MetaData to be encrypted but got: %t", innerDir.DirectoryMetaDataEncrypted)
}
if len(innerDir.MetaData) != 1 {
t.Fatalf("Expected MetaData to contain 1 item but got %d", len(innerDir.MetaData))
}
if innerDir.MetaData["hello"] != "world" {
t.Fatalf("Expected MetaData `hello` to be `world`: %s", innerDir.MetaData["hello"])
}
log.Printf("[DEBUG] Setting MetaData")
updatedMetaData := map[string]string{
"panda": "pops",
}
if _, err := directoriesClient.SetMetaData(ctx, accountName, shareName, "hello/there", updatedMetaData); err != nil {
t.Fatalf("Error updating MetaData: %s", err)
}
log.Printf("[DEBUG] Retrieving MetaData")
retrievedMetaData, err := directoriesClient.GetMetaData(ctx, accountName, shareName, "hello/there")
if err != nil {
t.Fatalf("Error retrieving the updated metadata: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected the updated metadata to have 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["panda"] != "pops" {
t.Fatalf("Expected the metadata `panda` to be `pops` but got %q", retrievedMetaData.MetaData["panda"])
}
t.Logf("[DEBUG] Deleting Inner..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello/there"); err != nil {
t.Fatalf("Error deleting Inner Directory: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level..")
if _, err := directoriesClient.Delete(ctx, accountName, shareName, "hello"); err != nil {
t.Fatalf("Error deleting Top Level Directory: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/file/directories/metadata_get.go 0000664 0000000 0000000 00000007127 14232154237 0024313 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns all user-defined metadata for the specified directory
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "GetMetaData", "`path` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/directories/metadata_set.go 0000664 0000000 0000000 00000007273 14232154237 0024331 0 ustar 00root root 0000000 0000000 package directories
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates user defined metadata for the specified directory
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("directories.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("directories.Client", "SetMetaData", "`path` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("directories.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "directories.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "directory"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/directories/resource_id.go 0000664 0000000 0000000 00000003113 14232154237 0024166 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Directory
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s", domain, shareName, directoryName)
}
type ResourceID struct {
AccountName string
DirectoryName string
ShareName string
}
// ParseResourceID parses the Resource ID into an Object
// which can be used to interact with the Directory within the File Share
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar/Folder
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/file/directories/resource_id_test.go 0000664 0000000 0000000 00000004246 14232154237 0025235 0 ustar 00root root 0000000 0000000 package directories
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/file/directories/version.go 0000664 0000000 0000000 00000000471 14232154237 0023354 0 ustar 00root root 0000000 0000000 package directories
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/file/files/ 0000775 0000000 0000000 00000000000 14232154237 0020124 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/file/files/README.md 0000664 0000000 0000000 00000002313 14232154237 0021402 0 ustar 00root root 0000000 0000000 ## File Storage Files SDK for API version 2020-08-04
This package allows you to interact with the Files File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Limitations
* At this time the headers `x-ms-file-permission` and `x-ms-file-attributes` are hard-coded (to `inherit` and `None`, respectively).
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/files"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
directoryName := "myfiles"
fileName := "example.txt"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
filesClient := files.New()
filesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := files.CreateInput{}
if _, err := filesClient.Create(ctx, accountName, shareName, directoryName, fileName, input); err != nil {
return fmt.Errorf("Error creating File: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/file/files/api.go 0000664 0000000 0000000 00000004234 14232154237 0021227 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"os"
"time"
"github.com/Azure/go-autorest/autorest"
)
type StorageFile interface {
PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error)
GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error)
ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error)
SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error)
PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error
Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error)
SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error)
AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error)
GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error)
GetResourceID(accountName, shareName, directoryName, filePath string) string
ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error)
GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error)
Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error)
CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error)
}
giovanni-0.20.0/storage/2020-08-04/file/files/client.go 0000664 0000000 0000000 00000001124 14232154237 0021727 0 ustar 00root root 0000000 0000000 package files
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/file/files/copy.go 0000664 0000000 0000000 00000011216 14232154237 0021426 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CopyInput struct {
// Specifies the URL of the source file or blob, up to 2 KB in length.
//
// To copy a file to another file within the same storage account, you may use Shared Key to authenticate
// the source file. If you are copying a file from another storage account, or if you are copying a blob from
// the same storage account or another storage account, then you must authenticate the source file or blob using a
// shared access signature. If the source is a public blob, no authentication is required to perform the copy
// operation. A file in a share snapshot can also be specified as a copy source.
CopySource string
MetaData map[string]string
}
type CopyResult struct {
autorest.Response
// The CopyID, which can be passed to AbortCopy to abort the copy.
CopyID string
// Either `success` or `pending`
CopySuccess string
}
// Copy copies a blob or file to a destination file within the storage account asynchronously.
func (client Client) Copy(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (result CopyResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Copy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Copy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Copy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Copy", "`fileName` cannot be an empty string.")
}
if input.CopySource == "" {
return result, validation.NewError("files.Client", "Copy", "`input.CopySource` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Copy", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CopyPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", nil, "Failure preparing request")
return
}
resp, err := client.CopySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure sending request")
return
}
result, err = client.CopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Copy", resp, "Failure responding to request")
return
}
return
}
// CopyPreparer prepares the Copy request.
func (client Client) CopyPreparer(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-source": input.CopySource,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CopySender sends the Copy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CopyResponder handles the response to the Copy request. The method always
// closes the http.Response Body.
func (client Client) CopyResponder(resp *http.Response) (result CopyResult, err error) {
if resp != nil && resp.Header != nil {
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopySuccess = resp.Header.Get("x-ms-copy-status")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/copy_abort.go 0000664 0000000 0000000 00000007157 14232154237 0022626 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// AbortCopy aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata
func (client Client) AbortCopy(ctx context.Context, accountName, shareName, path, fileName, copyID string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "AbortCopy", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`fileName` cannot be an empty string.")
}
if copyID == "" {
return result, validation.NewError("files.Client", "AbortCopy", "`copyID` cannot be an empty string.")
}
req, err := client.AbortCopyPreparer(ctx, accountName, shareName, path, fileName, copyID)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", nil, "Failure preparing request")
return
}
resp, err := client.AbortCopySender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure sending request")
return
}
result, err = client.AbortCopyResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "AbortCopy", resp, "Failure responding to request")
return
}
return
}
// AbortCopyPreparer prepares the AbortCopy request.
func (client Client) AbortCopyPreparer(ctx context.Context, accountName, shareName, path, fileName, copyID string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "copy"),
"copyid": autorest.Encode("query", copyID),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-copy-action": "abort",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// AbortCopySender sends the AbortCopy request. The method will close the
// http.Response Body if it receives an error.
func (client Client) AbortCopySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// AbortCopyResponder handles the response to the AbortCopy request. The method always
// closes the http.Response Body.
func (client Client) AbortCopyResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/copy_wait.go 0000664 0000000 0000000 00000002414 14232154237 0022452 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
)
type CopyAndWaitResult struct {
autorest.Response
CopyID string
}
const DefaultCopyPollDuration = 15 * time.Second
// CopyAndWait is a convenience method which doesn't exist in the API, which copies the file and then waits for the copy to complete
func (client Client) CopyAndWait(ctx context.Context, accountName, shareName, path, fileName string, input CopyInput, pollDuration time.Duration) (result CopyResult, err error) {
copy, e := client.Copy(ctx, accountName, shareName, path, fileName, input)
if err != nil {
result.Response = copy.Response
err = fmt.Errorf("Error copying: %s", e)
return
}
result.CopyID = copy.CopyID
// since the API doesn't return a LRO, this is a hack which also polls every 10s, but should be sufficient
for true {
props, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if e != nil {
result.Response = copy.Response
err = fmt.Errorf("Error waiting for copy: %s", e)
return
}
switch strings.ToLower(props.CopyStatus) {
case "pending":
time.Sleep(pollDuration)
continue
case "success":
return
default:
err = fmt.Errorf("Unexpected CopyState %q", e)
return
}
}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/copy_wait_test.go 0000664 0000000 0000000 00000011043 14232154237 0023507 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"strings"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestFilesCopyAndWaitFromURL(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
copiedFileName := "ubuntu.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
func TestFilesCopyAndWaitFromBlob(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
originalFileName := "ubuntu.iso"
copiedFileName := "ubuntu-copied.iso"
copyInput := CopyInput{
CopySource: "http://releases.ubuntu.com/14.04/ubuntu-14.04.6-desktop-amd64.iso",
}
t.Logf("[DEBUG] Copy And Waiting the original file..")
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", originalFileName, copyInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copy & waiting: %s", err)
}
t.Logf("[DEBUG] Now copying that blob..")
duplicateInput := CopyInput{
CopySource: fmt.Sprintf("%s/%s/%s", endpoints.GetFileEndpoint(filesClient.BaseURI, accountName), shareName, originalFileName),
}
if _, err := filesClient.CopyAndWait(ctx, accountName, shareName, "", copiedFileName, duplicateInput, DefaultCopyPollDuration); err != nil {
t.Fatalf("Error copying duplicate: %s", err)
}
t.Logf("[DEBUG] Asserting that the file's ready..")
props, err := filesClient.GetProperties(ctx, accountName, shareName, "", copiedFileName)
if err != nil {
t.Fatalf("Error retrieving file: %s", err)
}
if !strings.EqualFold(props.CopyStatus, "success") {
t.Fatalf("Expected the Copy Status to be `Success` but got %q", props.CopyStatus)
}
}
giovanni-0.20.0/storage/2020-08-04/file/files/create.go 0000664 0000000 0000000 00000013074 14232154237 0021723 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateInput struct {
// This header specifies the maximum size for the file, up to 1 TiB.
ContentLength int64
// The MIME content type of the file
// If not specified, the default type is application/octet-stream.
ContentType *string
// Specifies which content encodings have been applied to the file.
// This value is returned to the client when the Get File operation is performed
// on the file resource and can be used to decode file content.
ContentEncoding *string
// Specifies the natural languages used by this resource.
ContentLanguage *string
// The File service stores this value but does not use or modify it.
CacheControl *string
// Sets the file's MD5 hash.
ContentMD5 *string
// Sets the file’s Content-Disposition header.
ContentDisposition *string
// The time at which this file was created at - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-creation-time` field.
CreatedAt *time.Time
// The time at which this file was last modified - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-last-write-time` field.
LastModified *time.Time
// MetaData is a mapping of key value pairs which should be assigned to this file
MetaData map[string]string
}
// Create creates a new file or replaces a file.
func (client Client) Create(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Create", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Create", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("files.Client", "Create", "`input.MetaData` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName, path, fileName string, input CreateInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
var coalesceDate = func(input *time.Time, defaultVal string) string {
if input == nil {
return defaultVal
}
return input.Format(time.RFC1123)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-content-length": input.ContentLength,
"x-ms-type": "file",
"x-ms-file-permission": "inherit", // TODO: expose this in future
"x-ms-file-attributes": "None", // TODO: expose this in future
"x-ms-file-creation-time": coalesceDate(input.CreatedAt, "now"),
"x-ms-file-last-write-time": coalesceDate(input.LastModified, "now"),
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/delete.go 0000664 0000000 0000000 00000006206 14232154237 0021721 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete immediately deletes the file from the File Share.
func (client Client) Delete(ctx context.Context, accountName, shareName, path, fileName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "Delete", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "Delete", "`fileName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/lifecycle_test.go 0000664 0000000 0000000 00000012406 14232154237 0023454 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageFile = Client{}
func TestFilesLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 1,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
fileName := "bled5.png"
contentEncoding := "application/vnd+panda"
t.Logf("[DEBUG] Creating Top Level File..")
createInput := CreateInput{
ContentLength: 1024,
ContentEncoding: &contentEncoding,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Retrieving Properties for the Top-Level File..")
file, err := filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 1024 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != contentEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", contentEncoding, file.ContentEncoding)
}
updatedSize := int64(2048)
updatedEncoding := "application/vnd+pandas2"
updatedInput := SetPropertiesInput{
ContentEncoding: &updatedEncoding,
ContentLength: updatedSize,
MetaData: map[string]string{
"bingo": "bango",
},
}
t.Logf("[DEBUG] Setting Properties for the Top-Level File..")
if _, err := filesClient.SetProperties(ctx, accountName, shareName, "", fileName, updatedInput); err != nil {
t.Fatalf("Error setting properties: %s", err)
}
t.Logf("[DEBUG] Re-retrieving Properties for the Top-Level File..")
file, err = filesClient.GetProperties(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving Top-Level File: %s", err)
}
if *file.ContentLength != 2048 {
t.Fatalf("Expected the Content-Length to be 1024 but got %d", *file.ContentLength)
}
if file.ContentEncoding != updatedEncoding {
t.Fatalf("Expected the Content-Encoding to be %q but got %q", updatedEncoding, file.ContentEncoding)
}
if len(file.MetaData) != 1 {
t.Fatalf("Expected 1 item but got %d", len(file.MetaData))
}
if file.MetaData["bingo"] != "bango" {
t.Fatalf("Expected `bingo` to be `bango` but got %q", file.MetaData["bingo"])
}
t.Logf("[DEBUG] Setting MetaData..")
metaData := map[string]string{
"hello": "there",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Retrieving MetaData..")
retrievedMetaData, err := filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 1 {
t.Fatalf("Expected 1 item but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
t.Logf("[DEBUG] Re-Setting MetaData..")
metaData = map[string]string{
"hello": "there",
"second": "thing",
}
if _, err := filesClient.SetMetaData(ctx, accountName, shareName, "", fileName, metaData); err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
t.Logf("[DEBUG] Re-Retrieving MetaData..")
retrievedMetaData, err = filesClient.GetMetaData(ctx, accountName, shareName, "", fileName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(retrievedMetaData.MetaData) != 2 {
t.Fatalf("Expected 2 items but got %d", len(retrievedMetaData.MetaData))
}
if retrievedMetaData.MetaData["hello"] != "there" {
t.Fatalf("Expected `hello` to be `there` but got %q", retrievedMetaData.MetaData["hello"])
}
if retrievedMetaData.MetaData["second"] != "thing" {
t.Fatalf("Expected `second` to be `thing` but got %q", retrievedMetaData.MetaData["second"])
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/file/files/metadata_get.go 0000664 0000000 0000000 00000007263 14232154237 0023102 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData for the specified File.
func (client Client) GetMetaData(ctx context.Context, accountName, shareName, path, fileName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetMetaData", "`fileName` cannot be an empty string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil && resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
//metadata.ByParsingFromHeaders(&result.MetaData),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/metadata_set.go 0000664 0000000 0000000 00000007347 14232154237 0023121 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData updates the specified File to have the specified MetaData.
func (client Client) SetMetaData(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetMetaData", "`fileName` cannot be an empty string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("files.Client", "SetMetaData", fmt.Sprintf("`metaData` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, path, fileName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName, path, fileName string, metaData map[string]string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/properties_get.go 0000664 0000000 0000000 00000012141 14232154237 0023505 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetResult struct {
autorest.Response
CacheControl string
ContentDisposition string
ContentEncoding string
ContentLanguage string
ContentLength *int64
ContentMD5 string
ContentType string
CopyID string
CopyStatus string
CopySource string
CopyProgress string
CopyStatusDescription string
CopyCompletionTime string
Encrypted bool
MetaData map[string]string
}
// GetProperties returns the Properties for the specified file
func (client Client) GetProperties(ctx context.Context, accountName, shareName, path, fileName string) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsHead(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetResult, err error) {
if resp != nil && resp.Header != nil {
result.CacheControl = resp.Header.Get("Cache-Control")
result.ContentDisposition = resp.Header.Get("Content-Disposition")
result.ContentEncoding = resp.Header.Get("Content-Encoding")
result.ContentLanguage = resp.Header.Get("Content-Language")
result.ContentMD5 = resp.Header.Get("Content-MD5")
result.ContentType = resp.Header.Get("Content-Type")
result.CopyID = resp.Header.Get("x-ms-copy-id")
result.CopyProgress = resp.Header.Get("x-ms-copy-progress")
result.CopySource = resp.Header.Get("x-ms-copy-source")
result.CopyStatus = resp.Header.Get("x-ms-copy-status")
result.CopyStatusDescription = resp.Header.Get("x-ms-copy-status-description")
result.CopyCompletionTime = resp.Header.Get("x-ms-copy-completion-time")
result.Encrypted = strings.EqualFold(resp.Header.Get("x-ms-server-encrypted"), "true")
result.MetaData = metadata.ParseFromHeaders(resp.Header)
contentLengthRaw := resp.Header.Get("Content-Length")
if contentLengthRaw != "" {
contentLength, err := strconv.Atoi(contentLengthRaw)
if err != nil {
return result, fmt.Errorf("Error parsing %q for Content-Length as an integer: %s", contentLengthRaw, err)
}
contentLengthI64 := int64(contentLength)
result.ContentLength = &contentLengthI64
}
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/properties_set.go 0000664 0000000 0000000 00000015641 14232154237 0023531 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type SetPropertiesInput struct {
// Resizes a file to the specified size.
// If the specified byte value is less than the current size of the file,
// then all ranges above the specified byte value are cleared.
ContentLength int64
// Modifies the cache control string for the file.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentControl *string
// Sets the file’s Content-Disposition header.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentDisposition *string
// Sets the file's content encoding.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentEncoding *string
// Sets the file's content language.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentLanguage *string
// Sets the file's MD5 hash.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentMD5 *string
// Sets the file's content type.
// If this property is not specified on the request, then the property will be cleared for the file.
// Subsequent calls to Get File Properties will not return this property,
// unless it is explicitly set on the file again.
ContentType *string
// The time at which this file was created at - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-creation-time` field.
CreatedAt *time.Time
// The time at which this file was last modified - if omitted, this'll be set to "now"
// This maps to the `x-ms-file-last-write-time` field.
LastModified *time.Time
// MetaData is a mapping of key value pairs which should be assigned to this file
MetaData map[string]string
}
// SetProperties sets the specified properties on the specified File
func (client Client) SetProperties(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "SetProperties", "`fileName` cannot be an empty string.")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName, path, fileName string, input SetPropertiesInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
var coalesceDate = func(input *time.Time, defaultVal string) string {
if input == nil {
return defaultVal
}
return input.Format(time.RFC1123)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-type": "file",
"x-ms-content-length": input.ContentLength,
"x-ms-file-permission": "inherit", // TODO: expose this in future
"x-ms-file-attributes": "None", // TODO: expose this in future
"x-ms-file-creation-time": coalesceDate(input.CreatedAt, "now"),
"x-ms-file-last-write-time": coalesceDate(input.LastModified, "now"),
}
if input.ContentControl != nil {
headers["x-ms-cache-control"] = *input.ContentControl
}
if input.ContentDisposition != nil {
headers["x-ms-content-disposition"] = *input.ContentDisposition
}
if input.ContentEncoding != nil {
headers["x-ms-content-encoding"] = *input.ContentEncoding
}
if input.ContentLanguage != nil {
headers["x-ms-content-language"] = *input.ContentLanguage
}
if input.ContentMD5 != nil {
headers["x-ms-content-md5"] = *input.ContentMD5
}
if input.ContentType != nil {
headers["x-ms-content-type"] = *input.ContentType
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/range_clear.go 0000664 0000000 0000000 00000007740 14232154237 0022725 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ClearByteRangeInput struct {
StartBytes int64
EndBytes int64
}
// ClearByteRange clears the specified Byte Range from within the specified File
func (client Client) ClearByteRange(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ClearByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ClearByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "ClearByteRange", "`input.EndBytes` must be greater than 0.")
}
req, err := client.ClearByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", nil, "Failure preparing request")
return
}
resp, err := client.ClearByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure sending request")
return
}
result, err = client.ClearByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ClearByteRange", resp, "Failure responding to request")
return
}
return
}
// ClearByteRangePreparer prepares the ClearByteRange request.
func (client Client) ClearByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input ClearByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "clear",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes),
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ClearByteRangeSender sends the ClearByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ClearByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ClearByteRangeResponder handles the response to the ClearByteRange request. The method always
// closes the http.Response Body.
func (client Client) ClearByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/range_get.go 0000664 0000000 0000000 00000010430 14232154237 0022404 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetByteRangeInput struct {
StartBytes int64
EndBytes int64
}
type GetByteRangeResult struct {
autorest.Response
Contents []byte
}
// GetByteRange returns the specified Byte Range from the specified File.
func (client Client) GetByteRange(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (result GetByteRangeResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "GetByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "GetByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "GetByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
if expectedBytes < (4 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at least 4KB.")
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "GetByteRange", "Requested Byte Range must be at most 4MB.")
}
req, err := client.GetByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", nil, "Failure preparing request")
return
}
resp, err := client.GetByteRangeSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure sending request")
return
}
result, err = client.GetByteRangeResponder(resp, expectedBytes)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "GetByteRange", resp, "Failure responding to request")
return
}
return
}
// GetByteRangePreparer prepares the GetByteRange request.
func (client Client) GetByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input GetByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetByteRangeSender sends the GetByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetByteRangeResponder handles the response to the GetByteRange request. The method always
// closes the http.Response Body.
func (client Client) GetByteRangeResponder(resp *http.Response, length int64) (result GetByteRangeResult, err error) {
result.Contents = make([]byte, length)
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent),
autorest.ByUnmarshallingBytes(&result.Contents),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/range_get_file.go 0000664 0000000 0000000 00000006055 14232154237 0023413 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"log"
"math"
"runtime"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// GetFile is a helper method to download a file by chunking it automatically
func (client Client) GetFile(ctx context.Context, accountName, shareName, path, fileName string, parallelism int) (result autorest.Response, outputBytes []byte, err error) {
// first look up the file and check out how many bytes it is
file, e := client.GetProperties(ctx, accountName, shareName, path, fileName)
if err != nil {
result = file.Response
err = e
return
}
if file.ContentLength == nil {
err = fmt.Errorf("Content-Length was nil!")
return
}
length := int64(*file.ContentLength)
chunkSize := int64(4 * 1024 * 1024) // 4MB
if chunkSize > length {
chunkSize = length
}
// then split that up into chunks and retrieve it retrieve it into the 'results' set
chunks := int(math.Ceil(float64(length) / float64(chunkSize)))
workerCount := parallelism * runtime.NumCPU()
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
results := make([]*downloadFileChunkResult, chunks)
errors := make(chan error, chunkSize)
for i := 0; i < chunks; i++ {
go func(i int) {
log.Printf("[DEBUG] Downloading Chunk %d of %d", i+1, chunks)
dfci := downloadFileChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: length,
}
result, err := client.downloadFileChunk(ctx, accountName, shareName, path, fileName, dfci)
if err != nil {
errors <- err
waitGroup.Done()
return
}
// if there's no error, we should have bytes, so this is safe
results[i] = result
waitGroup.Done()
}(i)
}
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
err = fmt.Errorf("Error downloading file: %s", <-errors)
return
}
// then finally put it all together, in order and return it
output := make([]byte, length)
for _, v := range results {
copy(output[v.startBytes:v.endBytes], v.bytes)
}
outputBytes = output
return
}
type downloadFileChunkInput struct {
thisChunk int
chunkSize int64
fileSize int64
}
type downloadFileChunkResult struct {
startBytes int64
endBytes int64
bytes []byte
}
func (client Client) downloadFileChunk(ctx context.Context, accountName, shareName, path, fileName string, input downloadFileChunkInput) (*downloadFileChunkResult, error) {
startBytes := input.chunkSize * int64(input.thisChunk)
endBytes := startBytes + input.chunkSize
// the last chunk may exceed the size of the file
remaining := input.fileSize - startBytes
if input.chunkSize > remaining {
endBytes = startBytes + remaining
}
getInput := GetByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
}
result, err := client.GetByteRange(ctx, accountName, shareName, path, fileName, getInput)
if err != nil {
return nil, fmt.Errorf("Error putting bytes: %s", err)
}
output := downloadFileChunkResult{
startBytes: startBytes,
endBytes: endBytes,
bytes: result.Contents,
}
return &output, nil
}
giovanni-0.20.0/storage/2020-08-04/file/files/range_get_file_test.go 0000664 0000000 0000000 00000007063 14232154237 0024452 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestGetSmallFile(t *testing.T) {
// the purpose of this test is to verify that the small, single-chunked file gets downloaded correctly
testGetFile(t, "small-file.png", "image/png")
}
func TestGetLargeFile(t *testing.T) {
// the purpose of this test is to verify that the large, multi-chunked file gets downloaded correctly
testGetFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func testGetFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Downloading file..")
_, downloadedBytes, err := filesClient.GetFile(ctx, accountName, shareName, "", fileName, 4)
if err != nil {
t.Fatalf("Error downloading file: %s", err)
}
t.Logf("[DEBUG] Asserting the files are the same size..")
expectedBytes := make([]byte, info.Size())
file.Read(expectedBytes)
if len(expectedBytes) != len(downloadedBytes) {
t.Fatalf("Expected %d bytes but got %d", len(expectedBytes), len(downloadedBytes))
}
t.Logf("[DEBUG] Asserting the files are the same content-wise..")
// overkill, but it's this or shasum-ing
for i := int64(0); i < info.Size(); i++ {
if expectedBytes[i] != downloadedBytes[i] {
t.Fatalf("Expected byte %d to be %q but got %q", i, expectedBytes[i], downloadedBytes[i])
}
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/file/files/range_put.go 0000664 0000000 0000000 00000010777 14232154237 0022453 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutByteRangeInput struct {
StartBytes int64
EndBytes int64
// Content is the File Contents for the specified range
// which can be at most 4MB
Content []byte
}
// PutByteRange puts the specified Byte Range in the specified File.
func (client Client) PutByteRange(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "PutByteRange", "`shareName` must be a lower-cased string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "PutByteRange", "`fileName` cannot be an empty string.")
}
if input.StartBytes < 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.StartBytes` must be greater or equal to 0.")
}
if input.EndBytes <= 0 {
return result, validation.NewError("files.Client", "PutByteRange", "`input.EndBytes` must be greater than 0.")
}
expectedBytes := input.EndBytes - input.StartBytes
actualBytes := len(input.Content)
if expectedBytes != int64(actualBytes) {
return result, validation.NewError("files.Client", "PutByteRange", fmt.Sprintf("The specified byte-range (%d) didn't match the content size (%d).", expectedBytes, actualBytes))
}
if expectedBytes > (4 * 1024 * 1024) {
return result, validation.NewError("files.Client", "PutByteRange", "Specified Byte Range must be at most 4MB.")
}
req, err := client.PutByteRangePreparer(ctx, accountName, shareName, path, fileName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", nil, "Failure preparing request")
return
}
resp, err := client.PutByteRangeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure sending request")
return
}
result, err = client.PutByteRangeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "PutByteRange", resp, "Failure responding to request")
return
}
return
}
// PutByteRangePreparer prepares the PutByteRange request.
func (client Client) PutByteRangePreparer(ctx context.Context, accountName, shareName, path, fileName string, input PutByteRangeInput) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "range"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-write": "update",
"x-ms-range": fmt.Sprintf("bytes=%d-%d", input.StartBytes, input.EndBytes-1),
"Content-Length": int(len(input.Content)),
}
preparer := autorest.CreatePreparer(
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters),
autorest.WithBytes(&input.Content))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutByteRangeSender sends the PutByteRange request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutByteRangeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutByteRangeResponder handles the response to the PutByteRange request. The method always
// closes the http.Response Body.
func (client Client) PutByteRangeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/range_put_file.go 0000664 0000000 0000000 00000005070 14232154237 0023440 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"io"
"log"
"math"
"os"
"sync"
"github.com/Azure/go-autorest/autorest"
)
// PutFile is a helper method which takes a file, and automatically chunks it up, rather than having to do this yourself
func (client Client) PutFile(ctx context.Context, accountName, shareName, path, fileName string, file *os.File, parallelism int) error {
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("Error loading file info: %s", err)
}
fileSize := fileInfo.Size()
chunkSize := 4 * 1024 * 1024 // 4MB
if chunkSize > int(fileSize) {
chunkSize = int(fileSize)
}
chunks := int(math.Ceil(float64(fileSize) / float64(chunkSize*1.0)))
workerCount := parallelism
if workerCount > chunks {
workerCount = chunks
}
var waitGroup sync.WaitGroup
waitGroup.Add(workerCount)
jobs := make(chan int, workerCount)
errors := make(chan error, chunkSize)
for i := 0; i < workerCount; i++ {
go func() {
for i := range jobs {
log.Printf("[DEBUG] Chunk %d of %d", i+1, chunks)
uci := uploadChunkInput{
thisChunk: i,
chunkSize: chunkSize,
fileSize: fileSize,
}
_, err := client.uploadChunk(ctx, accountName, shareName, path, fileName, uci, file)
if err != nil {
errors <- err
}
}
waitGroup.Done()
}()
}
for i := 0; i < chunks; i++ {
jobs <- i
}
close(jobs)
waitGroup.Wait()
// TODO: we should switch to hashicorp/multi-error here
if len(errors) > 0 {
return fmt.Errorf("Error uploading file: %s", <-errors)
}
return nil
}
type uploadChunkInput struct {
thisChunk int
chunkSize int
fileSize int64
}
func (client Client) uploadChunk(ctx context.Context, accountName, shareName, path, fileName string, input uploadChunkInput, file *os.File) (result autorest.Response, err error) {
startBytes := int64(input.chunkSize * input.thisChunk)
endBytes := startBytes + int64(input.chunkSize)
// the last size may exceed the size of the file
remaining := input.fileSize - startBytes
if int64(input.chunkSize) > remaining {
endBytes = startBytes + remaining
}
bytesToRead := int(endBytes) - int(startBytes)
bytes := make([]byte, bytesToRead)
_, err = file.ReadAt(bytes, startBytes)
if err != nil {
if err != io.EOF {
return result, fmt.Errorf("Error reading bytes: %s", err)
}
}
putBytesInput := PutByteRangeInput{
StartBytes: startBytes,
EndBytes: endBytes,
Content: bytes,
}
result, err = client.PutByteRange(ctx, accountName, shareName, path, fileName, putBytesInput)
if err != nil {
return result, fmt.Errorf("Error putting bytes: %s", err)
}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/range_put_file_test.go 0000664 0000000 0000000 00000005712 14232154237 0024502 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"os"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/shares"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
func TestPutSmallFile(t *testing.T) {
// the purpose of this test is to ensure that a small file (< 4MB) is a single chunk
testPutFile(t, "small-file.png", "image/png")
}
func TestPutLargeFile(t *testing.T) {
// the purpose of this test is to ensure that large files (> 4MB) are chunked
testPutFile(t, "blank-large-file.dmg", "application/x-apple-diskimage")
}
func TestPutVerySmallFile(t *testing.T) {
// the purpose of this test is to ensure that a very small file (< 4KB) is a single chunk
testPutFile(t, "very-small.json", "application/json")
}
func testPutFile(t *testing.T, fileName string, contentType string) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := shares.NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := shares.CreateInput{
QuotaInGB: 10,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
defer sharesClient.Delete(ctx, accountName, shareName, false)
filesClient := NewWithEnvironment(client.Environment)
filesClient.Client = client.PrepareWithAuthorizer(filesClient.Client, storageAuth)
// store files outside of this directory, since they're reused
file, err := os.Open("../../../testdata/" + fileName)
if err != nil {
t.Fatalf("Error opening: %s", err)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("Error 'stat'-ing: %s", err)
}
t.Logf("[DEBUG] Creating Top Level File..")
createFileInput := CreateInput{
ContentLength: info.Size(),
ContentType: &contentType,
}
if _, err := filesClient.Create(ctx, accountName, shareName, "", fileName, createFileInput); err != nil {
t.Fatalf("Error creating Top-Level File: %s", err)
}
t.Logf("[DEBUG] Uploading File..")
if err := filesClient.PutFile(ctx, accountName, shareName, "", fileName, file, 4); err != nil {
t.Fatalf("Error uploading File: %s", err)
}
t.Logf("[DEBUG] Deleting Top Level File..")
if _, err := filesClient.Delete(ctx, accountName, shareName, "", fileName); err != nil {
t.Fatalf("Error deleting Top-Level File: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/file/files/ranges_list.go 0000664 0000000 0000000 00000007277 14232154237 0023002 0 ustar 00root root 0000000 0000000 package files
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ListRangesResult struct {
autorest.Response
Ranges []Range `xml:"Range"`
}
type Range struct {
Start string `xml:"Start"`
End string `xml:"End"`
}
// ListRanges returns the list of valid ranges for the specified File.
func (client Client) ListRanges(ctx context.Context, accountName, shareName, path, fileName string) (result ListRangesResult, err error) {
if accountName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("files.Client", "ListRanges", "`shareName` must be a lower-cased string.")
}
if path == "" {
return result, validation.NewError("files.Client", "ListRanges", "`path` cannot be an empty string.")
}
if fileName == "" {
return result, validation.NewError("files.Client", "ListRanges", "`fileName` cannot be an empty string.")
}
req, err := client.ListRangesPreparer(ctx, accountName, shareName, path, fileName)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", nil, "Failure preparing request")
return
}
resp, err := client.ListRangesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure sending request")
return
}
result, err = client.ListRangesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "files.Client", "ListRanges", resp, "Failure responding to request")
return
}
return
}
// ListRangesPreparer prepares the ListRanges request.
func (client Client) ListRangesPreparer(ctx context.Context, accountName, shareName, path, fileName string) (*http.Request, error) {
if path != "" {
path = fmt.Sprintf("%s/", path)
}
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
"directory": autorest.Encode("path", path),
"fileName": autorest.Encode("path", fileName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "rangelist"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}/{directory}{fileName}", pathParameters),
autorest.WithHeaders(headers),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ListRangesSender sends the ListRanges request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ListRangesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ListRangesResponder handles the response to the ListRanges request. The method always
// closes the http.Response Body.
func (client Client) ListRangesResponder(resp *http.Response) (result ListRangesResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/files/resource_id.go 0000664 0000000 0000000 00000003654 14232154237 0022766 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName, directoryName, filePath string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/%s/%s", domain, shareName, directoryName, filePath)
}
type ResourceID struct {
AccountName string
DirectoryName string
FileName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with Files within a Storage Share.
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt
// example: https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) == 0 {
return nil, fmt.Errorf("Expected the path to contain segments but got none")
}
shareName := segments[0]
fileName := segments[len(segments)-1]
directoryName := strings.TrimPrefix(path, shareName)
directoryName = strings.TrimPrefix(directoryName, "/")
directoryName = strings.TrimSuffix(directoryName, fileName)
directoryName = strings.TrimSuffix(directoryName, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
DirectoryName: directoryName,
FileName: fileName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/file/files/resource_id_test.go 0000664 0000000 0000000 00000007430 14232154237 0024021 0 ustar 00root root 0000000 0000000 package files
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1", "directory1", "file1.txt")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/file1.txt",
},
}
t.Logf("[DEBUG] Top Level Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1" {
t.Fatalf("Expected Directory Name to be `directory1` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
testData = []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1/directory1/directory2/file1.txt",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1/directory1/directory2/file1.txt",
},
}
t.Logf("[DEBUG] Nested Files")
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected Share Name to be `share1` but got %q", actual.ShareName)
}
if actual.DirectoryName != "directory1/directory2" {
t.Fatalf("Expected Directory Name to be `directory1/directory2` but got %q", actual.DirectoryName)
}
if actual.FileName != "file1.txt" {
t.Fatalf("Expected File Name to be `file1.txt` but got %q", actual.FileName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/file/files/version.go 0000664 0000000 0000000 00000000463 14232154237 0022143 0 ustar 00root root 0000000 0000000 package files
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/file/shares/ 0000775 0000000 0000000 00000000000 14232154237 0020307 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/file/shares/README.md 0000664 0000000 0000000 00000001777 14232154237 0021602 0 ustar 00root root 0000000 0000000 ## File Storage Shares SDK for API version 2020-08-04
This package allows you to interact with the Shares File Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/shares"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
shareName := "myshare"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
sharesClient := shares.New()
sharesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := shares.CreateInput{
QuotaInGB: 2,
}
if _, err := sharesClient.Create(ctx, accountName, shareName, input); err != nil {
return fmt.Errorf("Error creating Share: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/file/shares/acl_get.go 0000664 0000000 0000000 00000006213 14232154237 0022236 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL get the Access Control List for the specified Storage Share
func (client Client) GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.GetACLPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/acl_set.go 0000664 0000000 0000000 00000006415 14232154237 0022256 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"encoding/xml"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List on the specified Storage Share
func (client Client) SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetACL", "`shareName` must be a lower-cased string.")
}
req, err := client.SetACLPreparer(ctx, accountName, shareName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/api.go 0000664 0000000 0000000 00000003221 14232154237 0021405 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageShare interface {
SetACL(ctx context.Context, accountName, shareName string, acls []SignedIdentifier) (result autorest.Response, err error)
GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error)
GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error)
GetACL(ctx context.Context, accountName, shareName string) (result GetACLResult, err error)
SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error)
SetProperties(ctx context.Context, accountName, shareName string, properties ShareProperties) (result autorest.Response, err error)
DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error)
CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error)
GetResourceID(accountName, shareName string) string
GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, shareName string) string
GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error)
Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error)
Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2020-08-04/file/shares/client.go 0000664 0000000 0000000 00000001125 14232154237 0022113 0 ustar 00root root 0000000 0000000 package shares
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for File Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/file/shares/create.go 0000664 0000000 0000000 00000010633 14232154237 0022104 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type AccessTier string
const (
TransactionOptimizedAccessTier AccessTier = "TransactionOptimized"
HotAccessTier AccessTier = "Hot"
CoolAccessTier AccessTier = "Cool"
PremiumAccessTier AccessTier = "Premium"
)
type CreateInput struct {
// Specifies the maximum size of the share, in gigabytes.
// Must be greater than 0, and less than or equal to 5TB (5120).
QuotaInGB int
// Specifies the enabled protocols on the share. If not specified, the default is SMB.
EnabledProtocol ShareProtocol
MetaData map[string]string
// Specifies the access tier of the share.
AccessTier *AccessTier
}
// Create creates the specified Storage Share within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, shareName string, input CreateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Create", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Create", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Create", "`shareName` must be a lower-cased string.")
}
if input.QuotaInGB <= 0 || input.QuotaInGB > 102400 {
return result, validation.NewError("shares.Client", "Create", "`input.QuotaInGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "Create", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, shareName string, input CreateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"x-ms-share-quota": input.QuotaInGB,
}
protocol := SMB
if input.EnabledProtocol != "" {
protocol = input.EnabledProtocol
}
headers["x-ms-enabled-protocols"] = protocol
if input.AccessTier != nil {
headers["x-ms-access-tier"] = string(*input.AccessTier)
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/delete.go 0000664 0000000 0000000 00000006120 14232154237 0022077 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Storage Share from within a Storage Account
func (client Client) Delete(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "Delete", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "Delete", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "Delete", "`shareName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, shareName, deleteSnapshots)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, shareName string, deleteSnapshots bool) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if deleteSnapshots {
headers["x-ms-delete-snapshots"] = "include"
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/lifecycle_test.go 0000664 0000000 0000000 00000025070 14232154237 0023640 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageShare = Client{}
func TestSharesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorageV2)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
tier := CoolAccessTier
input := CreateInput{
QuotaInGB: 1,
AccessTier: &tier,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.QuotaInGB != 1 {
t.Fatalf("Expected Quota to be 1 but got: %d", share.QuotaInGB)
}
if share.EnabledProtocol != SMB {
t.Fatalf("Expected EnabledProtocol to SMB but got: %s", share.EnabledProtocol)
}
if share.AccessTier == nil || *share.AccessTier != CoolAccessTier {
t.Fatalf("Expected AccessTier to be Cool but got: %v", share.AccessTier)
}
newTier := HotAccessTier
quota := 5
props := ShareProperties{
AccessTier: &newTier,
QuotaInGb: "a,
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, props)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.QuotaInGB != 5 {
t.Fatalf("Expected Quota to be 5 but got: %d", share.QuotaInGB)
}
if share.AccessTier == nil || *share.AccessTier != HotAccessTier {
t.Fatalf("Expected AccessTier to be Hot but got: %v", share.AccessTier)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
func TestSharesLifecycleLargeQuota(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResourcesWithSku(ctx, resourceGroup, accountName, storage.KindFileStorage, storage.SkuNamePremiumLRS)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1001,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
snapshot, err := sharesClient.CreateSnapshot(ctx, accountName, shareName, CreateSnapshotInput{})
if err != nil {
t.Fatalf("Error taking snapshot: %s", err)
}
t.Logf("Snapshot Date Time: %s", snapshot.SnapshotDateTime)
snapshotDetails, err := sharesClient.GetSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error retrieving snapshot: %s", err)
}
t.Logf("MetaData: %s", snapshotDetails.MetaData)
_, err = sharesClient.DeleteSnapshot(ctx, accountName, shareName, snapshot.SnapshotDateTime)
if err != nil {
t.Fatalf("Error deleting snapshot: %s", err)
}
stats, err := sharesClient.GetStats(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving stats: %s", err)
}
if stats.ShareUsageBytes != 0 {
t.Fatalf("Expected `stats.ShareUsageBytes` to be 0 but got: %d", stats.ShareUsageBytes)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.QuotaInGB != 1001 {
t.Fatalf("Expected Quota to be 1001 but got: %d", share.QuotaInGB)
}
newQuota := 6000
props := ShareProperties{
QuotaInGb: &newQuota,
}
_, err = sharesClient.SetProperties(ctx, accountName, shareName, props)
if err != nil {
t.Fatalf("Error updating quota: %s", err)
}
share, err = sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.QuotaInGB != 6000 {
t.Fatalf("Expected Quota to be 6000 but got: %d", share.QuotaInGB)
}
updatedMetaData := map[string]string{
"hello": "world",
}
_, err = sharesClient.SetMetaData(ctx, accountName, shareName, updatedMetaData)
if err != nil {
t.Fatalf("Erorr setting metadata: %s", err)
}
result, err := sharesClient.GetMetaData(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving metadata: %s", err)
}
if result.MetaData["hello"] != "world" {
t.Fatalf("Expected metadata `hello` to be `world` but got: %q", result.MetaData["hello"])
}
if len(result.MetaData) != 1 {
t.Fatalf("Expected metadata to be 1 item but got: %s", result.MetaData)
}
acls, err := sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 0 {
t.Fatalf("Expected 0 identifiers but got %d", len(acls.SignedIdentifiers))
}
updatedAcls := []SignedIdentifier{
{
Id: "abc123",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
{
Id: "bcd234",
AccessPolicy: AccessPolicy{
Start: "2020-07-01T08:49:37.0000000Z",
Expiry: "2020-07-01T09:49:37.0000000Z",
Permission: "rwd",
},
},
}
_, err = sharesClient.SetACL(ctx, accountName, shareName, updatedAcls)
if err != nil {
t.Fatalf("Error setting ACL's: %s", err)
}
acls, err = sharesClient.GetACL(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving ACL's: %s", err)
}
if len(acls.SignedIdentifiers) != 2 {
t.Fatalf("Expected 2 identifiers but got %d", len(acls.SignedIdentifiers))
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
func TestSharesLifecycleNFSProtocol(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
shareName := fmt.Sprintf("share-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResourcesWithSku(ctx, resourceGroup, accountName, storage.KindFileStorage, storage.SkuNamePremiumLRS)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
sharesClient := NewWithEnvironment(client.Environment)
sharesClient.Client = client.PrepareWithAuthorizer(sharesClient.Client, storageAuth)
input := CreateInput{
QuotaInGB: 1000,
EnabledProtocol: NFS,
}
_, err = sharesClient.Create(ctx, accountName, shareName, input)
if err != nil {
t.Fatalf("Error creating fileshare: %s", err)
}
share, err := sharesClient.GetProperties(ctx, accountName, shareName)
if err != nil {
t.Fatalf("Error retrieving share: %s", err)
}
if share.EnabledProtocol != NFS {
t.Fatalf(`Expected enabled protocol to be "NFS" but got: %q`, share.EnabledProtocol)
}
_, err = sharesClient.Delete(ctx, accountName, shareName, false)
if err != nil {
t.Fatalf("Error deleting Share: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/file/shares/metadata_get.go 0000664 0000000 0000000 00000006525 14232154237 0023265 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the MetaData associated with the specified Storage Share
func (client Client) GetMetaData(ctx context.Context, accountName, shareName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetMetaData", "`shareName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/metadata_set.go 0000664 0000000 0000000 00000006703 14232154237 0023277 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData sets the MetaData on the specified Storage Share
func (client Client) SetMetaData(ctx context.Context, accountName, shareName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetMetaData", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("shares.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, shareName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, shareName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/models.go 0000664 0000000 0000000 00000001034 14232154237 0022117 0 ustar 00root root 0000000 0000000 package shares
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
type ShareProtocol string
const (
// SMB indicates the share can be accessed by SMBv3.0, SMBv2.1 and REST.
SMB ShareProtocol = "SMB"
// NFS indicates the share can be accessed by NFSv4.1. A premium account is required for this option.
NFS ShareProtocol = "NFS"
)
giovanni-0.20.0/storage/2020-08-04/file/shares/properties_get.go 0000664 0000000 0000000 00000007774 14232154237 0023710 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetPropertiesResult struct {
autorest.Response
MetaData map[string]string
QuotaInGB int
EnabledProtocol ShareProtocol
AccessTier *AccessTier
}
// GetProperties returns the properties about the specified Storage Share
func (client Client) GetProperties(ctx context.Context, accountName, shareName string) (result GetPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetProperties", "`shareName` must be a lower-cased string.")
}
req, err := client.GetPropertiesPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetPropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure sending request")
return
}
result, err = client.GetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetProperties", resp, "Failure responding to request")
return
}
return
}
// GetPropertiesPreparer prepares the GetProperties request.
func (client Client) GetPropertiesPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetPropertiesSender sends the GetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetPropertiesResponder handles the response to the GetProperties request. The method always
// closes the http.Response Body.
func (client Client) GetPropertiesResponder(resp *http.Response) (result GetPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
quotaRaw := resp.Header.Get("x-ms-share-quota")
if quotaRaw != "" {
quota, e := strconv.Atoi(quotaRaw)
if e != nil {
return result, fmt.Errorf("Error converting %q to an integer: %s", quotaRaw, err)
}
result.QuotaInGB = quota
}
protocol := SMB
if protocolRaw := resp.Header.Get("x-ms-enabled-protocols"); protocolRaw != "" {
protocol = ShareProtocol(protocolRaw)
}
if accessTierRaw := resp.Header.Get("x-ms-access-tier"); accessTierRaw != "" {
tier := AccessTier(accessTierRaw)
result.AccessTier = &tier
}
result.EnabledProtocol = protocol
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/properties_set.go 0000664 0000000 0000000 00000007317 14232154237 0023715 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type ShareProperties struct {
QuotaInGb *int
AccessTier *AccessTier
}
// SetProperties lets you update the Quota for the specified Storage Share
func (client Client) SetProperties(ctx context.Context, accountName, shareName string, properties ShareProperties) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "SetProperties", "`shareName` must be a lower-cased string.")
}
if newQuotaGB := properties.QuotaInGb; newQuotaGB != nil && (*newQuotaGB <= 0 || *newQuotaGB > 102400) {
return result, validation.NewError("shares.Client", "SetProperties", "`newQuotaGB` must be greater than 0, and less than/equal to 100TB (102400 GB)")
}
req, err := client.SetPropertiesPreparer(ctx, accountName, shareName, properties)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetPropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure sending request")
return
}
result, err = client.SetPropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "SetProperties", resp, "Failure responding to request")
return
}
return
}
// SetPropertiesPreparer prepares the SetProperties request.
func (client Client) SetPropertiesPreparer(ctx context.Context, accountName, shareName string, properties ShareProperties) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "properties"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
if properties.QuotaInGb != nil {
headers["x-ms-share-quota"] = *properties.QuotaInGb
}
if properties.AccessTier != nil {
headers["x-ms-access-tier"] = string(*properties.AccessTier)
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetPropertiesSender sends the SetProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetPropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetPropertiesResponder handles the response to the SetProperties request. The method always
// closes the http.Response Body.
func (client Client) SetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/resource_id.go 0000664 0000000 0000000 00000003217 14232154237 0023144 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given File Share
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, shareName string) string {
domain := endpoints.GetFileEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, shareName)
}
// GetResourceManagerResourceID returns the Resource Manager specific
// ResourceID for a specific Storage Share
func (client Client) GetResourceManagerResourceID(subscriptionID, resourceGroup, accountName, shareName string) string {
fmtStr := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/%s/fileServices/default/shares/%s"
return fmt.Sprintf(fmtStr, subscriptionID, resourceGroup, accountName, shareName)
}
type ResourceID struct {
AccountName string
ShareName string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Storage Shares SDK
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.file.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
shareName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
ShareName: shareName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/file/shares/resource_id_test.go 0000664 0000000 0000000 00000006514 14232154237 0024206 0 ustar 00root root 0000000 0000000 package shares
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestGetResourceManagerResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.GermanCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.PublicCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "/subscriptions/11112222-3333-4444-5555-666677778888/resourceGroups/group1/providers/Microsoft.Storage/storageAccounts/account1/fileServices/default/shares/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceManagerResourceID("11112222-3333-4444-5555-666677778888", "group1", "account1", "share1")
if actual != v.Expected {
t.Fatalf("Expected the Resource Manager Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.file.core.chinacloudapi.cn/share1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.file.core.cloudapi.de/share1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.file.core.windows.net/share1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.file.core.usgovcloudapi.net/share1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.ShareName != "share1" {
t.Fatalf("Expected the share name to be `share1` but got %q", actual.ShareName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/file/shares/snapshot_create.go 0000664 0000000 0000000 00000010266 14232154237 0024025 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type CreateSnapshotInput struct {
MetaData map[string]string
}
type CreateSnapshotResult struct {
autorest.Response
// This header is a DateTime value that uniquely identifies the share snapshot.
// The value of this header may be used in subsequent requests to access the share snapshot.
// This value is opaque.
SnapshotDateTime string
}
// CreateSnapshot creates a read-only snapshot of the share
// A share can support creation of 200 share snapshots. Attempting to create more than 200 share snapshots fails with 409 (Conflict).
// Attempting to create a share snapshot while a previous Snapshot Share operation is in progress fails with 409 (Conflict).
func (client Client) CreateSnapshot(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (result CreateSnapshotResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "CreateSnapshot", "`shareName` must be a lower-cased string.")
}
if err := metadata.Validate(input.MetaData); err != nil {
return result, validation.NewError("shares.Client", "CreateSnapshot", fmt.Sprintf("`input.MetaData` is not valid: %s.", err))
}
req, err := client.CreateSnapshotPreparer(ctx, accountName, shareName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.CreateSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure sending request")
return
}
result, err = client.CreateSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "CreateSnapshot", resp, "Failure responding to request")
return
}
return
}
// CreateSnapshotPreparer prepares the CreateSnapshot request.
func (client Client) CreateSnapshotPreparer(ctx context.Context, accountName, shareName string, input CreateSnapshotInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "snapshot"),
"restype": autorest.Encode("query", "share"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, input.MetaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSnapshotSender sends the CreateSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateSnapshotResponder handles the response to the CreateSnapshot request. The method always
// closes the http.Response Body.
func (client Client) CreateSnapshotResponder(resp *http.Response) (result CreateSnapshotResult, err error) {
result.SnapshotDateTime = resp.Header.Get("x-ms-snapshot")
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/snapshot_delete.go 0000664 0000000 0000000 00000006552 14232154237 0024027 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// DeleteSnapshot deletes the specified Snapshot of a Storage Share
func (client Client) DeleteSnapshot(ctx context.Context, accountName, shareName string, shareSnapshot string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareName` must be a lower-cased string.")
}
if shareSnapshot == "" {
return result, validation.NewError("shares.Client", "DeleteSnapshot", "`shareSnapshot` cannot be an empty string.")
}
req, err := client.DeleteSnapshotPreparer(ctx, accountName, shareName, shareSnapshot)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSnapshotSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure sending request")
return
}
result, err = client.DeleteSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "DeleteSnapshot", resp, "Failure responding to request")
return
}
return
}
// DeleteSnapshotPreparer prepares the DeleteSnapshot request.
func (client Client) DeleteSnapshotPreparer(ctx context.Context, accountName, shareName string, shareSnapshot string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("path", "share"),
"sharesnapshot": autorest.Encode("query", shareSnapshot),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSnapshotSender sends the DeleteSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteSnapshotResponder handles the response to the DeleteSnapshot request. The method always
// closes the http.Response Body.
func (client Client) DeleteSnapshotResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/snapshot_get.go 0000664 0000000 0000000 00000007101 14232154237 0023333 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetSnapshotPropertiesResult struct {
autorest.Response
MetaData map[string]string
}
// GetSnapshot gets information about the specified Snapshot of the specified Storage Share
func (client Client) GetSnapshot(ctx context.Context, accountName, shareName, snapshotShare string) (result GetSnapshotPropertiesResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetSnapshot", "`shareName` must be a lower-cased string.")
}
if snapshotShare == "" {
return result, validation.NewError("shares.Client", "GetSnapshot", "`snapshotShare` cannot be an empty string.")
}
req, err := client.GetSnapshotPreparer(ctx, accountName, shareName, snapshotShare)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", nil, "Failure preparing request")
return
}
resp, err := client.GetSnapshotSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure sending request")
return
}
result, err = client.GetSnapshotResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetSnapshot", resp, "Failure responding to request")
return
}
return
}
// GetSnapshotPreparer prepares the GetSnapshot request.
func (client Client) GetSnapshotPreparer(ctx context.Context, accountName, shareName, snapshotShare string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"snapshot": autorest.Encode("query", snapshotShare),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSnapshotSender sends the GetSnapshot request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSnapshotSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetSnapshotResponder handles the response to the GetSnapshot request. The method always
// closes the http.Response Body.
func (client Client) GetSnapshotResponder(resp *http.Response) (result GetSnapshotPropertiesResult, err error) {
if resp.Header != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/stats.go 0000664 0000000 0000000 00000006470 14232154237 0022003 0 ustar 00root root 0000000 0000000 package shares
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetStatsResult struct {
autorest.Response
// The approximate size of the data stored on the share.
// Note that this value may not include all recently created or recently resized files.
ShareUsageBytes int64 `xml:"ShareUsageBytes"`
}
// GetStats returns information about the specified Storage Share
func (client Client) GetStats(ctx context.Context, accountName, shareName string) (result GetStatsResult, err error) {
if accountName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`accountName` cannot be an empty string.")
}
if shareName == "" {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` cannot be an empty string.")
}
if strings.ToLower(shareName) != shareName {
return result, validation.NewError("shares.Client", "GetStats", "`shareName` must be a lower-cased string.")
}
req, err := client.GetStatsPreparer(ctx, accountName, shareName)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", nil, "Failure preparing request")
return
}
resp, err := client.GetStatsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure sending request")
return
}
result, err = client.GetStatsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "shares.Client", "GetStats", resp, "Failure responding to request")
return
}
return
}
// GetStatsPreparer prepares the GetStats request.
func (client Client) GetStatsPreparer(ctx context.Context, accountName, shareName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"shareName": autorest.Encode("path", shareName),
}
queryParameters := map[string]interface{}{
"restype": autorest.Encode("query", "share"),
"comp": autorest.Encode("query", "stats"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetFileEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{shareName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetStatsSender sends the GetStats request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetStatsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetStatsResponder handles the response to the GetStats request. The method always
// closes the http.Response Body.
func (client Client) GetStatsResponder(resp *http.Response) (result GetStatsResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/file/shares/version.go 0000664 0000000 0000000 00000000464 14232154237 0022327 0 ustar 00root root 0000000 0000000 package shares
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/queue/ 0000775 0000000 0000000 00000000000 14232154237 0017227 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/queue/messages/ 0000775 0000000 0000000 00000000000 14232154237 0021036 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/queue/messages/README.md 0000664 0000000 0000000 00000002062 14232154237 0022315 0 ustar 00root root 0000000 0000000 ## Queue Storage Messages SDK for API version 2020-08-04
This package allows you to interact with the Messages Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/queue/messages"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
messagesClient := messages.New()
messagesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := messages.PutInput{
Message: "hello",
}
if _, err := messagesClient.Put(ctx, accountName, queueName, input); err != nil {
return fmt.Errorf("Error creating Message: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/queue/messages/api.go 0000664 0000000 0000000 00000001466 14232154237 0022145 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageQueueMessage interface {
Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error)
Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error)
GetResourceID(accountName, queueName, messageID string) string
Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error)
Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error)
Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/client.go 0000664 0000000 0000000 00000001114 14232154237 0022640 0 ustar 00root root 0000000 0000000 package messages
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Messages.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/delete.go 0000664 0000000 0000000 00000006523 14232154237 0022635 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes a specific message
func (client Client) Delete(ctx context.Context, accountName, queueName, messageID, popReceipt string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Delete", "`queueName` must be a lower-cased string.")
}
if messageID == "" {
return result, validation.NewError("messages.Client", "Delete", "`messageID` cannot be an empty string.")
}
if popReceipt == "" {
return result, validation.NewError("messages.Client", "Delete", "`popReceipt` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName, messageID, popReceipt)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, queueName, messageID, popReceipt string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", popReceipt),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/get.go 0000664 0000000 0000000 00000007666 14232154237 0022163 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetInput struct {
// VisibilityTimeout specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
VisibilityTimeout *int
}
// Get retrieves one or more messages from the front of the queue
func (client Client) Get(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Get", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Get", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Get", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Get", "`numberOfMessages` must be between 1 and 32.")
}
if input.VisibilityTimeout != nil {
t := *input.VisibilityTimeout
maxTime := (time.Hour * 24 * 7).Seconds()
if t < 1 || t < int(maxTime) {
return result, validation.NewError("messages.Client", "Get", "`input.VisibilityTimeout` must be larger than or equal to 1 second, and cannot be larger than 7 days.")
}
}
req, err := client.GetPreparer(ctx, accountName, queueName, numberOfMessages, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int, input GetInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("query", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/lifecycle_test.go 0000664 0000000 0000000 00000005565 14232154237 0024376 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/queue/queues"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageQueueMessage = Client{}
func TestLifeCycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := queues.NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
storageAuth := auth.NewSharedKeyLiteAuthorizer(accountName, testData.StorageAccountKey)
messagesClient := NewWithEnvironment(client.Environment)
messagesClient.Client = client.PrepareWithAuthorizer(messagesClient.Client, storageAuth)
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error creating queue: %s", err)
}
defer queuesClient.Delete(ctx, accountName, queueName)
input := PutInput{
Message: "ohhai",
}
putResp, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message in queue: %s", err)
}
messageId := (*putResp.QueueMessages)[0].MessageId
popReceipt := (*putResp.QueueMessages)[0].PopReceipt
_, err = messagesClient.Update(ctx, accountName, queueName, messageId, UpdateInput{
PopReceipt: popReceipt,
Message: "Updated message",
VisibilityTimeout: 65,
})
if err != nil {
t.Fatalf("Error updating: %s", err)
}
for i := 0; i < 5; i++ {
input := PutInput{
Message: fmt.Sprintf("Message %d", i),
}
_, err := messagesClient.Put(ctx, accountName, queueName, input)
if err != nil {
t.Fatalf("Error putting message %d in queue: %s", i, err)
}
}
peakedMessages, err := messagesClient.Peek(ctx, accountName, queueName, 3)
if err != nil {
t.Fatalf("Error peaking messages: %s", err)
}
for _, v := range *peakedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
}
retrievedMessages, err := messagesClient.Get(ctx, accountName, queueName, 6, GetInput{})
if err != nil {
t.Fatalf("Error retrieving messages: %s", err)
}
for _, v := range *retrievedMessages.QueueMessages {
t.Logf("Message: %q", v.MessageId)
_, err = messagesClient.Delete(ctx, accountName, queueName, v.MessageId, v.PopReceipt)
if err != nil {
t.Fatalf("Error deleting message from queue: %s", err)
}
}
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/models.go 0000664 0000000 0000000 00000001010 14232154237 0022640 0 ustar 00root root 0000000 0000000 package messages
import "github.com/Azure/go-autorest/autorest"
type QueueMessage struct {
MessageText string `xml:"MessageText"`
}
type QueueMessagesListResult struct {
autorest.Response
QueueMessages *[]QueueMessageResponse `xml:"QueueMessage"`
}
type QueueMessageResponse struct {
MessageId string `xml:"MessageId"`
InsertionTime string `xml:"InsertionTime"`
ExpirationTime string `xml:"ExpirationTime"`
PopReceipt string `xml:"PopReceipt"`
TimeNextVisible string `xml:"TimeNextVisible"`
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/peek.go 0000664 0000000 0000000 00000006512 14232154237 0022315 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Peek retrieves one or more messages from the front of the queue, but doesn't alter the visibility of the messages
func (client Client) Peek(ctx context.Context, accountName, queueName string, numberOfMessages int) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Peek", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Peek", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Peek", "`queueName` must be a lower-cased string.")
}
if numberOfMessages < 1 || numberOfMessages > 32 {
return result, validation.NewError("messages.Client", "Peek", "`numberOfMessages` must be between 1 and 32.")
}
req, err := client.PeekPreparer(ctx, accountName, queueName, numberOfMessages)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", nil, "Failure preparing request")
return
}
resp, err := client.PeekSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure sending request")
return
}
result, err = client.PeekResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Peek", resp, "Failure responding to request")
return
}
return
}
// PeekPreparer prepares the Peek request.
func (client Client) PeekPreparer(ctx context.Context, accountName, queueName string, numberOfMessages int) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"numofmessages": autorest.Encode("query", numberOfMessages),
"peekonly": autorest.Encode("query", true),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PeekSender sends the Peek request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PeekSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PeekResponder handles the response to the Peek request. The method always
// closes the http.Response Body.
func (client Client) PeekResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/put.go 0000664 0000000 0000000 00000010107 14232154237 0022174 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type PutInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// The maximum time-to-live can be any positive number,
// as well as -1 indicating that the message does not expire.
// If this parameter is omitted, the default time-to-live is 7 days.
MessageTtl *int
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// visibilitytimeout should be set to a value smaller than the time-to-live value.
// If not specified, the default value is 0.
VisibilityTimeout *int
}
// Put adds a new message to the back of the message queue
func (client Client) Put(ctx context.Context, accountName, queueName string, input PutInput) (result QueueMessagesListResult, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Put", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Put", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Put", "`queueName` must be a lower-cased string.")
}
req, err := client.PutPreparer(ctx, accountName, queueName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", nil, "Failure preparing request")
return
}
resp, err := client.PutSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure sending request")
return
}
result, err = client.PutResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Put", resp, "Failure responding to request")
return
}
return
}
// PutPreparer prepares the Put request.
func (client Client) PutPreparer(ctx context.Context, accountName, queueName string, input PutInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{}
if input.MessageTtl != nil {
queryParameters["messagettl"] = autorest.Encode("path", *input.MessageTtl)
}
if input.VisibilityTimeout != nil {
queryParameters["visibilitytimeout"] = autorest.Encode("path", *input.VisibilityTimeout)
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// PutSender sends the Put request. The method will close the
// http.Response Body if it receives an error.
func (client Client) PutSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// PutResponder handles the response to the Put request. The method always
// closes the http.Response Body.
func (client Client) PutResponder(resp *http.Response) (result QueueMessagesListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
autorest.ByUnmarshallingXML(&result),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/resource_id.go 0000664 0000000 0000000 00000003044 14232154237 0023671 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Message within a Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName, messageID string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s/messages/%s", domain, queueName, messageID)
}
type ResourceID struct {
AccountName string
QueueName string
MessageID string
}
// ParseResourceID parses the specified Resource ID and returns an object
// which can be used to interact with the Message within a Queue
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
path := strings.TrimPrefix(uri.Path, "/")
segments := strings.Split(path, "/")
if len(segments) != 3 {
return nil, fmt.Errorf("Expected the path to contain 3 segments but got %d", len(segments))
}
queueName := segments[0]
messageID := segments[2]
return &ResourceID{
AccountName: *accountName,
MessageID: messageID,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/resource_id_test.go 0000664 0000000 0000000 00000004321 14232154237 0024727 0 ustar 00root root 0000000 0000000 package messages
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1", "message1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1/messages/message1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1/messages/message1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1/messages/message1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1/messages/message1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected Queue Name to be `queue1` but got %q", actual.QueueName)
}
if actual.MessageID != "message1" {
t.Fatalf("Expected Message ID to be `message1` but got %q", actual.MessageID)
}
}
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/update.go 0000664 0000000 0000000 00000010071 14232154237 0022646 0 ustar 00root root 0000000 0000000 package messages
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type UpdateInput struct {
// A message must be in a format that can be included in an XML request with UTF-8 encoding.
// The encoded message can be up to 64 KB in size.
Message string
// Specifies the valid pop receipt value required to modify this message.
PopReceipt string
// Specifies the new visibility timeout value, in seconds, relative to server time.
// The new value must be larger than or equal to 0, and cannot be larger than 7 days.
// The visibility timeout of a message cannot be set to a value later than the expiry time.
// A message can be updated until it has been deleted or has expired.
VisibilityTimeout int
}
// Update updates an existing message based on it's Pop Receipt
func (client Client) Update(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("messages.Client", "Update", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("messages.Client", "Update", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("messages.Client", "Update", "`queueName` must be a lower-cased string.")
}
if input.PopReceipt == "" {
return result, validation.NewError("messages.Client", "Update", "`input.PopReceipt` cannot be an empty string.")
}
req, err := client.UpdatePreparer(ctx, accountName, queueName, messageID, input)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", nil, "Failure preparing request")
return
}
resp, err := client.UpdateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure sending request")
return
}
result, err = client.UpdateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "messages.Client", "Update", resp, "Failure responding to request")
return
}
return
}
// UpdatePreparer prepares the Update request.
func (client Client) UpdatePreparer(ctx context.Context, accountName, queueName string, messageID string, input UpdateInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
"messageID": autorest.Encode("path", messageID),
}
queryParameters := map[string]interface{}{
"popreceipt": autorest.Encode("query", input.PopReceipt),
"visibilitytimeout": autorest.Encode("query", input.VisibilityTimeout),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
body := QueueMessage{
MessageText: input.Message,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}/messages/{messageID}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// UpdateSender sends the Update request. The method will close the
// http.Response Body if it receives an error.
func (client Client) UpdateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// UpdateResponder handles the response to the Update request. The method always
// closes the http.Response Body.
func (client Client) UpdateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/messages/version.go 0000664 0000000 0000000 00000000466 14232154237 0023060 0 ustar 00root root 0000000 0000000 package messages
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/ 0000775 0000000 0000000 00000000000 14232154237 0020536 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/queue/queues/README.md 0000664 0000000 0000000 00000002013 14232154237 0022011 0 ustar 00root root 0000000 0000000 ## Queue Storage Queues SDK for API version 2020-08-04
This package allows you to interact with the Queues Queue Storage API
### Supported Authorizers
* Azure Active Directory (for the Resource Endpoint `https://storage.azure.com`)
* SharedKeyLite (Blob, File & Queue)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/queue/queues"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
queueName := "myqueue"
storageAuth := autorest.NewSharedKeyLiteAuthorizer(accountName, storageAccountKey)
queuesClient := queues.New()
queuesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
metadata := map[string]string{
"hello": "world",
}
if _, err := queuesClient.Create(ctx, accountName, queueName, metadata); err != nil {
return fmt.Errorf("Error creating Queue: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/queue/queues/api.go 0000664 0000000 0000000 00000001556 14232154237 0021645 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageQueue interface {
Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error)
GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error)
SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error)
Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error)
GetResourceID(accountName, queueName string) string
SetServiceProperties(ctx context.Context, accountName string, properties StorageServiceProperties) (result autorest.Response, err error)
GetServiceProperties(ctx context.Context, accountName string) (result StorageServicePropertiesResponse, err error)
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/client.go 0000664 0000000 0000000 00000001126 14232154237 0022343 0 ustar 00root root 0000000 0000000 package queues
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Queue Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/create.go 0000664 0000000 0000000 00000006247 14232154237 0022341 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// Create creates the specified Queue within the specified Storage Account
func (client Client) Create(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Create", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Create", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Create", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "Create", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.CreatePreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName string, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusCreated),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/delete.go 0000664 0000000 0000000 00000005502 14232154237 0022331 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified Queue within the specified Storage Account
func (client Client) Delete(ctx context.Context, accountName, queueName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "Delete", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "Delete", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "Delete", "`queueName` must be a lower-cased string.")
}
req, err := client.DeletePreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName string, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/lifecycle_test.go 0000664 0000000 0000000 00000014166 14232154237 0024073 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageQueue = Client{}
func TestQueuesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
queueName := fmt.Sprintf("queue-%d", testhelpers.RandomInt())
_, err = client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
queuesClient := NewWithEnvironment(client.Environment)
queuesClient.Client = client.PrepareWithStorageResourceManagerAuth(queuesClient.Client)
// first let's test an empty container
_, err = queuesClient.Create(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatal(fmt.Errorf("Error creating: %s", err))
}
// then let's retrieve it to ensure there's no metadata..
resp, err := queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// then let's add some..
updatedMetaData := map[string]string{
"band": "panic",
"boots": "the-overpass",
}
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, updatedMetaData)
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error re-retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 2 {
t.Fatalf("Expected metadata to have 2 items but got: %s", resp.MetaData)
}
if resp.MetaData["band"] != "panic" {
t.Fatalf("Expected `band` to be `panic` but got: %s", resp.MetaData["band"])
}
if resp.MetaData["boots"] != "the-overpass" {
t.Fatalf("Expected `boots` to be `the-overpass` but got: %s", resp.MetaData["boots"])
}
// and woo let's remove it again
_, err = queuesClient.SetMetaData(ctx, accountName, queueName, map[string]string{})
if err != nil {
t.Fatalf("Error setting MetaData: %s", err)
}
resp, err = queuesClient.GetMetaData(ctx, accountName, queueName)
if err != nil {
t.Fatalf("Error retrieving MetaData: %s", err)
}
if len(resp.MetaData) != 0 {
t.Fatalf("Expected no MetaData but got: %s", err)
}
// set some properties
props := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "GET,PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
CorsRule{
AllowedMethods: "POST",
AllowedOrigins: "http://www.test.com",
ExposedHeaders: "*",
AllowedHeaders: "x-method-*",
MaxAgeInSeconds: 200,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err := queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) > 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "GET,PUT" {
t.Fatalf("CORS Methods weren't set!")
}
if properties.Cors.CorsRule[1].AllowedMethods != "POST" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
includeAPIS := true
// set some properties
props2 := StorageServiceProperties{
Logging: &LoggingConfig{
Version: "1.0",
Delete: true,
Read: true,
Write: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
Cors: &Cors{
CorsRule: []CorsRule{
CorsRule{
AllowedMethods: "PUT",
AllowedOrigins: "http://www.example.com",
ExposedHeaders: "x-tempo-*",
AllowedHeaders: "x-tempo-*",
MaxAgeInSeconds: 500,
},
},
},
HourMetrics: &MetricsConfig{
Version: "1.0",
Enabled: true,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
IncludeAPIs: &includeAPIS,
},
MinuteMetrics: &MetricsConfig{
Version: "1.0",
Enabled: false,
RetentionPolicy: RetentionPolicy{
Enabled: true,
Days: 7,
},
},
}
_, err = queuesClient.SetServiceProperties(ctx, accountName, props2)
if err != nil {
t.Fatalf("SetServiceProperties failed: %s", err)
}
properties, err = queuesClient.GetServiceProperties(ctx, accountName)
if err != nil {
t.Fatalf("GetServiceProperties failed: %s", err)
}
if len(properties.Cors.CorsRule) == 1 {
if properties.Cors.CorsRule[0].AllowedMethods != "PUT" {
t.Fatalf("CORS Methods weren't set!")
}
} else {
t.Fatalf("CORS Methods weren't set!")
}
if !properties.HourMetrics.Enabled {
t.Fatalf("HourMetrics were enabled when they shouldn't be!")
}
if properties.MinuteMetrics.Enabled {
t.Fatalf("MinuteMetrics were enabled when they shouldn't be!")
}
if !properties.Logging.Write {
t.Fatalf("Logging Write's was not enabled when they should be!")
}
log.Printf("[DEBUG] Deleting..")
_, err = queuesClient.Delete(ctx, accountName, queueName)
if err != nil {
t.Fatal(fmt.Errorf("Error deleting: %s", err))
}
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/metadata_get.go 0000664 0000000 0000000 00000006376 14232154237 0023520 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
type GetMetaDataResult struct {
autorest.Response
MetaData map[string]string
}
// GetMetaData returns the metadata for this Queue
func (client Client) GetMetaData(ctx context.Context, accountName, queueName string) (result GetMetaDataResult, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "GetMetaData", "`queueName` must be a lower-cased string.")
}
req, err := client.GetMetaDataPreparer(ctx, accountName, queueName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.GetMetaDataSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure sending request")
return
}
result, err = client.GetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetMetaData", resp, "Failure responding to request")
return
}
return
}
// GetMetaDataPreparer prepares the GetMetaData request.
func (client Client) GetMetaDataPreparer(ctx context.Context, accountName, queueName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetMetaDataSender sends the GetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetMetaDataResponder handles the response to the GetMetaData request. The method always
// closes the http.Response Body.
func (client Client) GetMetaDataResponder(resp *http.Response) (result GetMetaDataResult, err error) {
if resp != nil {
result.MetaData = metadata.ParseFromHeaders(resp.Header)
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/metadata_set.go 0000664 0000000 0000000 00000006576 14232154237 0023536 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
"github.com/tombuildsstuff/giovanni/storage/internal/metadata"
)
// SetMetaData returns the metadata for this Queue
func (client Client) SetMetaData(ctx context.Context, accountName, queueName string, metaData map[string]string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`accountName` cannot be an empty string.")
}
if queueName == "" {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` cannot be an empty string.")
}
if strings.ToLower(queueName) != queueName {
return result, validation.NewError("queues.Client", "SetMetaData", "`queueName` must be a lower-cased string.")
}
if err := metadata.Validate(metaData); err != nil {
return result, validation.NewError("queues.Client", "SetMetaData", fmt.Sprintf("`metadata` is not valid: %s.", err))
}
req, err := client.SetMetaDataPreparer(ctx, accountName, queueName, metaData)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", nil, "Failure preparing request")
return
}
resp, err := client.SetMetaDataSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure sending request")
return
}
result, err = client.SetMetaDataResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetMetaData", resp, "Failure responding to request")
return
}
return
}
// SetMetaDataPreparer prepares the SetMetaData request.
func (client Client) SetMetaDataPreparer(ctx context.Context, accountName, queueName string, metaData map[string]string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"queueName": autorest.Encode("path", queueName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "metadata"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
headers = metadata.SetIntoHeaders(headers, metaData)
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{queueName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetMetaDataSender sends the SetMetaData request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetMetaDataSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetMetaDataResponder handles the response to the SetMetaData request. The method always
// closes the http.Response Body.
func (client Client) SetMetaDataResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/models.go 0000664 0000000 0000000 00000002410 14232154237 0022345 0 ustar 00root root 0000000 0000000 package queues
type StorageServiceProperties struct {
Logging *LoggingConfig `xml:"Logging,omitempty"`
HourMetrics *MetricsConfig `xml:"HourMetrics,omitempty"`
MinuteMetrics *MetricsConfig `xml:"MinuteMetrics,omitempty"`
Cors *Cors `xml:"Cors,omitempty"`
}
type LoggingConfig struct {
Version string `xml:"Version"`
Delete bool `xml:"Delete"`
Read bool `xml:"Read"`
Write bool `xml:"Write"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
}
type MetricsConfig struct {
Version string `xml:"Version"`
Enabled bool `xml:"Enabled"`
RetentionPolicy RetentionPolicy `xml:"RetentionPolicy"`
// Element IncludeAPIs is only expected when Metrics is enabled
IncludeAPIs *bool `xml:"IncludeAPIs,omitempty"`
}
type RetentionPolicy struct {
Enabled bool `xml:"Enabled"`
Days int `xml:"Days,omitempty"`
}
type Cors struct {
CorsRule []CorsRule `xml:"CorsRule"`
}
type CorsRule struct {
AllowedOrigins string `xml:"AllowedOrigins"`
AllowedMethods string `xml:"AllowedMethods"`
AllowedHeaders string `xml:"AllowedHeaders`
ExposedHeaders string `xml:"ExposedHeaders"`
MaxAgeInSeconds int `xml:"MaxAgeInSeconds"`
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/properties_get.go 0000664 0000000 0000000 00000005670 14232154237 0024130 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type StorageServicePropertiesResponse struct {
StorageServiceProperties
autorest.Response
}
// SetServiceProperties gets the properties for this queue
func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result StorageServicePropertiesResponse, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "GetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.GetServicePropertiesPreparer(ctx, accountName)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.GetServicePropertiesSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.GetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "GetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// GetServicePropertiesPreparer prepares the GetServiceProperties request.
func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetServicePropertiesSender sends the GetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetServicePropertiesResponder handles the response to the GetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) GetServicePropertiesResponder(resp *http.Response) (result StorageServicePropertiesResponse, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/properties_set.go 0000664 0000000 0000000 00000005575 14232154237 0024150 0 ustar 00root root 0000000 0000000 package queues
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// SetServiceProperties sets the properties for this queue
func (client Client) SetServiceProperties(ctx context.Context, accountName string, properties StorageServiceProperties) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("queues.Client", "SetServiceProperties", "`accountName` cannot be an empty string.")
}
req, err := client.SetServicePropertiesPreparer(ctx, accountName, properties)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", nil, "Failure preparing request")
return
}
resp, err := client.SetServicePropertiesSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure sending request")
return
}
result, err = client.SetServicePropertiesResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "queues.Client", "SetServiceProperties", resp, "Failure responding to request")
return
}
return
}
// SetServicePropertiesPreparer prepares the SetServiceProperties request.
func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, properties StorageServiceProperties) (*http.Request, error) {
queryParameters := map[string]interface{}{
"comp": autorest.Encode("path", "properties"),
"restype": autorest.Encode("path", "service"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetQueueEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/"),
autorest.WithQueryParameters(queryParameters),
autorest.WithXML(properties),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always
// closes the http.Response Body.
func (client Client) SetServicePropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusAccepted),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/resource_id.go 0000664 0000000 0000000 00000002315 14232154237 0023371 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Queue
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, queueName string) string {
domain := endpoints.GetQueueEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s", domain, queueName)
}
type ResourceID struct {
AccountName string
QueueName string
}
// ParseResourceID parses the Resource ID and returns an Object which
// can be used to interact with a Queue within a Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.queue.core.windows.net/Bar
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
queueName := strings.TrimPrefix(uri.Path, "/")
return &ResourceID{
AccountName: *accountName,
QueueName: queueName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/resource_id_test.go 0000664 0000000 0000000 00000003701 14232154237 0024430 0 ustar 00root root 0000000 0000000 package queues
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "queue1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.queue.core.chinacloudapi.cn/queue1",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.queue.core.cloudapi.de/queue1",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.queue.core.windows.net/queue1",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.queue.core.usgovcloudapi.net/queue1",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected the account name to be `account1` but got %q", actual.AccountName)
}
if actual.QueueName != "queue1" {
t.Fatalf("Expected the queue name to be `queue1` but got %q", actual.QueueName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/queue/queues/version.go 0000664 0000000 0000000 00000000464 14232154237 0022556 0 ustar 00root root 0000000 0000000 package queues
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/table/ 0000775 0000000 0000000 00000000000 14232154237 0017172 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/table/entities/ 0000775 0000000 0000000 00000000000 14232154237 0021016 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/table/entities/README.md 0000664 0000000 0000000 00000002166 14232154237 0022302 0 ustar 00root root 0000000 0000000 ## Table Storage Entities SDK for API version 2020-08-04
This package allows you to interact with the Entities Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/table/entities"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
entitiesClient := entities.New()
entitiesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
input := entities.InsertEntityInput{
PartitionKey: "abc",
RowKey: "123",
MetaDataLevel: entities.NoMetaData,
Entity: map[string]interface{}{
"title": "Don't Kill My Vibe",
"artist": "Sigrid",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, input); err != nil {
return fmt.Errorf("Error creating Entity: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/table/entities/api.go 0000664 0000000 0000000 00000001700 14232154237 0022114 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageTableEntity interface {
Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error)
Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error)
InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error)
InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error)
Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error)
Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error)
GetResourceID(accountName, tableName, partitionKey, rowKey string) string
}
giovanni-0.20.0/storage/2020-08-04/table/entities/client.go 0000664 0000000 0000000 00000001130 14232154237 0022616 0 ustar 00root root 0000000 0000000 package entities
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/table/entities/delete.go 0000664 0000000 0000000 00000007327 14232154237 0022620 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type DeleteEntityInput struct {
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Delete deletes an existing entity in a table.
func (client Client) Delete(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Delete", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Delete", "`input.RowKey` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string, input DeleteEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
// TODO: support for eTags
"If-Match": "*",
}
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/entities/get.go 0000664 0000000 0000000 00000007013 14232154237 0022125 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetEntityInput struct {
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
}
type GetEntityResult struct {
autorest.Response
Entity map[string]interface{}
}
// Get queries entities in a table and includes the $filter and $select options.
func (client Client) Get(ctx context.Context, accountName, tableName string, input GetEntityInput) (result GetEntityResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Get", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Get", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Get", "`input.RowKey` cannot be an empty string.")
}
req, err := client.GetPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Get", resp, "Failure responding to request")
return
}
return
}
// GetPreparer prepares the Get request.
func (client Client) GetPreparer(ctx context.Context, accountName, tableName string, input GetEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client Client) GetResponder(resp *http.Response) (result GetEntityResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result.Entity),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/entities/insert.go 0000664 0000000 0000000 00000010207 14232154237 0022651 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertEntityInput struct {
// The level of MetaData provided for this Entity
MetaDataLevel MetaDataLevel
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// Insert inserts a new entity into a table.
func (client Client) Insert(ctx context.Context, accountName, tableName string, input InsertEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Insert", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Insert", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "Insert", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", nil, "Failure preparing request")
return
}
resp, err := client.InsertSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure sending request")
return
}
result, err = client.InsertResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Insert", resp, "Failure responding to request")
return
}
return
}
// InsertPreparer prepares the Insert request.
func (client Client) InsertPreparer(ctx context.Context, accountName, tableName string, input InsertEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"Prefer": "return-no-content",
}
input.Entity["PartitionKey"] = input.PartitionKey
input.Entity["RowKey"] = input.RowKey
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertSender sends the Insert request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertResponder handles the response to the Insert request. The method always
// closes the http.Response Body.
func (client Client) InsertResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/entities/insert_or_merge.go 0000664 0000000 0000000 00000010625 14232154237 0024534 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrMergeEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrMerge updates an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrMerge(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrMerge", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrMergePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrMergeSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure sending request")
return
}
result, err = client.InsertOrMergeResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrMerge", resp, "Failure responding to request")
return
}
return
}
// InsertOrMergePreparer prepares the InsertOrMerge request.
func (client Client) InsertOrMergePreparer(ctx context.Context, accountName, tableName string, input InsertOrMergeEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrMergeSender sends the InsertOrMerge request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrMergeSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrMergeResponder handles the response to the InsertOrMerge request. The method always
// closes the http.Response Body.
func (client Client) InsertOrMergeResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/entities/insert_or_replace.go 0000664 0000000 0000000 00000010706 14232154237 0025050 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type InsertOrReplaceEntityInput struct {
// The Entity which should be inserted, by default all values are strings
// To explicitly type a property, specify the appropriate OData data type by setting
// the m:type attribute within the property definition
Entity map[string]interface{}
// When inserting an entity into a table, you must specify values for the PartitionKey and RowKey system properties.
// Together, these properties form the primary key and must be unique within the table.
// Both the PartitionKey and RowKey values must be string values; each key value may be up to 64 KB in size.
// If you are using an integer value for the key value, you should convert the integer to a fixed-width string,
// because they are canonically sorted. For example, you should convert the value 1 to 0000001 to ensure proper sorting.
RowKey string
PartitionKey string
}
// InsertOrReplace replaces an existing entity or inserts a new entity if it does not exist in the table.
// Because this operation can insert or update an entity, it is also known as an upsert operation.
func (client Client) InsertOrReplace(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`tableName` cannot be an empty string.")
}
if input.PartitionKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.PartitionKey` cannot be an empty string.")
}
if input.RowKey == "" {
return result, validation.NewError("entities.Client", "InsertOrReplace", "`input.RowKey` cannot be an empty string.")
}
req, err := client.InsertOrReplacePreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", nil, "Failure preparing request")
return
}
resp, err := client.InsertOrReplaceSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure sending request")
return
}
result, err = client.InsertOrReplaceResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "InsertOrReplace", resp, "Failure responding to request")
return
}
return
}
// InsertOrReplacePreparer prepares the InsertOrReplace request.
func (client Client) InsertOrReplacePreparer(ctx context.Context, accountName, tableName string, input InsertOrReplaceEntityInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"partitionKey": autorest.Encode("path", input.PartitionKey),
"rowKey": autorest.Encode("path", input.RowKey),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json",
"Prefer": "return-no-content",
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsMerge(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}(PartitionKey='{partitionKey}', RowKey='{rowKey}')", pathParameters),
autorest.WithJSON(input.Entity),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// InsertOrReplaceSender sends the InsertOrReplace request. The method will close the
// http.Response Body if it receives an error.
func (client Client) InsertOrReplaceSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// InsertOrReplaceResponder handles the response to the InsertOrReplace request. The method always
// closes the http.Response Body.
func (client Client) InsertOrReplaceResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/entities/lifecycle_test.go 0000664 0000000 0000000 00000010202 14232154237 0024336 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/table/tables"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageTableEntity = Client{}
func TestEntitiesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := tables.NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
defer tablesClient.Delete(ctx, accountName, tableName)
entitiesClient := NewWithEnvironment(client.Environment)
entitiesClient.Client = client.PrepareWithAuthorizer(entitiesClient.Client, storageAuth)
partitionKey := "hello"
rowKey := "there"
t.Logf("[DEBUG] Inserting..")
insertInput := InsertEntityInput{
MetaDataLevel: NoMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "world",
},
}
if _, err := entitiesClient.Insert(ctx, accountName, tableName, insertInput); err != nil {
t.Logf("Error retrieving: %s", err)
}
t.Logf("[DEBUG] Insert or Merging..")
insertOrMergeInput := InsertOrMergeEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "ther88e",
},
}
if _, err := entitiesClient.InsertOrMerge(ctx, accountName, tableName, insertOrMergeInput); err != nil {
t.Logf("Error insert/merging: %s", err)
}
t.Logf("[DEBUG] Insert or Replacing..")
insertOrReplaceInput := InsertOrReplaceEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
Entity: map[string]interface{}{
"hello": "pandas",
},
}
if _, err := entitiesClient.InsertOrReplace(ctx, accountName, tableName, insertOrReplaceInput); err != nil {
t.Logf("Error inserting/replacing: %s", err)
}
t.Logf("[DEBUG] Querying..")
queryInput := QueryEntitiesInput{
MetaDataLevel: NoMetaData,
}
results, err := entitiesClient.Query(ctx, accountName, tableName, queryInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
if len(results.Entities) != 1 {
t.Fatalf("Expected 1 item but got %d", len(results.Entities))
}
for _, v := range results.Entities {
thisPartitionKey := v["PartitionKey"].(string)
thisRowKey := v["RowKey"].(string)
if partitionKey != thisPartitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, thisPartitionKey)
}
if rowKey != thisRowKey {
t.Fatalf("Expected Partition Key to be %q but got %q", rowKey, thisRowKey)
}
}
t.Logf("[DEBUG] Retrieving..")
getInput := GetEntityInput{
MetaDataLevel: MinimalMetaData,
PartitionKey: partitionKey,
RowKey: rowKey,
}
getResults, err := entitiesClient.Get(ctx, accountName, tableName, getInput)
if err != nil {
t.Logf("Error querying: %s", err)
}
partitionKey2 := getResults.Entity["PartitionKey"].(string)
rowKey2 := getResults.Entity["RowKey"].(string)
if partitionKey2 != partitionKey {
t.Fatalf("Expected Partition Key to be %q but got %q", partitionKey, partitionKey2)
}
if rowKey2 != rowKey {
t.Fatalf("Expected Row Key to be %q but got %q", rowKey, rowKey2)
}
t.Logf("[DEBUG] Deleting..")
deleteInput := DeleteEntityInput{
PartitionKey: partitionKey,
RowKey: rowKey,
}
if _, err := entitiesClient.Delete(ctx, accountName, tableName, deleteInput); err != nil {
t.Logf("Error deleting: %s", err)
}
}
giovanni-0.20.0/storage/2020-08-04/table/entities/models.go 0000664 0000000 0000000 00000000306 14232154237 0022627 0 ustar 00root root 0000000 0000000 package entities
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
giovanni-0.20.0/storage/2020-08-04/table/entities/query.go 0000664 0000000 0000000 00000012065 14232154237 0022516 0 ustar 00root root 0000000 0000000 package entities
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type QueryEntitiesInput struct {
// An optional OData filter
Filter *string
// An optional comma-separated
PropertyNamesToSelect *[]string
// An optional OData top
Top *int
PartitionKey string
RowKey string
// The Level of MetaData which should be returned
MetaDataLevel MetaDataLevel
// The Next Partition Key used to load data from a previous point
NextPartitionKey *string
// The Next Row Key used to load data from a previous point
NextRowKey *string
}
type QueryEntitiesResult struct {
autorest.Response
NextPartitionKey string
NextRowKey string
MetaData string `json:"odata.metadata,omitempty"`
Entities []map[string]interface{} `json:"value"`
}
// Query queries entities in a table and includes the $filter and $select options.
func (client Client) Query(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (result QueryEntitiesResult, err error) {
if accountName == "" {
return result, validation.NewError("entities.Client", "Query", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("entities.Client", "Query", "`tableName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, tableName, input)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "entities.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName, tableName string, input QueryEntitiesInput) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
"additionalParameters": "",
}
//PartitionKey='',RowKey=''
additionalParams := make([]string, 0)
if input.PartitionKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("PartitionKey='%s'", input.PartitionKey))
}
if input.RowKey != "" {
additionalParams = append(additionalParams, fmt.Sprintf("RowKey='%s'", input.RowKey))
}
if len(additionalParams) > 0 {
pathParameters["additionalParameters"] = autorest.Encode("path", strings.Join(additionalParams, ","))
}
queryParameters := map[string]interface{}{}
if input.Filter != nil {
queryParameters["$filter"] = autorest.Encode("query", *input.Filter)
}
if input.PropertyNamesToSelect != nil {
queryParameters["$select"] = autorest.Encode("query", strings.Join(*input.PropertyNamesToSelect, ","))
}
if input.Top != nil {
queryParameters["$top"] = autorest.Encode("query", *input.Top)
}
if input.NextPartitionKey != nil {
queryParameters["NextPartitionKey"] = *input.NextPartitionKey
}
if input.NextRowKey != nil {
queryParameters["NextRowKey"] = *input.NextRowKey
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", input.MetaDataLevel),
"DataServiceVersion": "3.0;NetFx",
"MaxDataServiceVersion": "3.0;NetFx",
}
// GET /myaccount/Customers()?$filter=(Rating%20ge%203)%20and%20(Rating%20le%206)&$select=PartitionKey,RowKey,Address,CustomerSince
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}({additionalParameters})", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result QueryEntitiesResult, err error) {
if resp != nil && resp.Header != nil {
result.NextPartitionKey = resp.Header.Get("x-ms-continuation-NextPartitionKey")
result.NextRowKey = resp.Header.Get("x-ms-continuation-NextRowKey")
}
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/entities/resource_id.go 0000664 0000000 0000000 00000005370 14232154237 0023655 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Entity
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName, partitionKey, rowKey string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/%s(PartitionKey='%s',RowKey='%s')", domain, tableName, partitionKey, rowKey)
}
type ResourceID struct {
AccountName string
TableName string
PartitionKey string
RowKey string
}
// ParseResourceID parses the specified Resource ID and returns an object which
// can be used to look up the specified Entity within the specified Table
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.Contains(uri.Path, "(") || !strings.HasSuffix(uri.Path, ")") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `tables(PartitionKey='',RowKey='')` but got %q", path)
}
// NOTE: honestly this could probably be a RegEx, but this seemed like the simplest way to
// allow these two fields to be specified in either order
indexOfBracket := strings.IndexByte(path, '(')
tableName := path[0:indexOfBracket]
// trim off the brackets
temp := strings.TrimPrefix(path, fmt.Sprintf("%s(", tableName))
temp = strings.TrimSuffix(temp, ")")
dictionary := strings.Split(temp, ",")
partitionKey := ""
rowKey := ""
for _, v := range dictionary {
split := strings.Split(v, "=")
if len(split) != 2 {
return nil, fmt.Errorf("Expected 2 segments but got %d for %q", len(split), v)
}
key := split[0]
value := strings.TrimSuffix(strings.TrimPrefix(split[1], "'"), "'")
if strings.EqualFold(key, "PartitionKey") {
partitionKey = value
} else if strings.EqualFold(key, "RowKey") {
rowKey = value
} else {
return nil, fmt.Errorf("Unexpected Key %q", key)
}
}
if partitionKey == "" {
return nil, fmt.Errorf("Expected a PartitionKey but didn't get one")
}
if rowKey == "" {
return nil, fmt.Errorf("Expected a RowKey but didn't get one")
}
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
PartitionKey: partitionKey,
RowKey: rowKey,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/table/entities/resource_id_test.go 0000664 0000000 0000000 00000005012 14232154237 0024705 0 ustar 00root root 0000000 0000000 package entities
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1", "partition1", "row1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/table1(PartitionKey='partition1',RowKey='row1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/table1(PartitionKey='partition1',RowKey='row1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
if actual.PartitionKey != "partition1" {
t.Fatalf("Expected Partition Key to be `partition1` but got %q", actual.PartitionKey)
}
if actual.RowKey != "row1" {
t.Fatalf("Expected Row Key to be `row1` but got %q", actual.RowKey)
}
}
}
giovanni-0.20.0/storage/2020-08-04/table/entities/version.go 0000664 0000000 0000000 00000000466 14232154237 0023040 0 ustar 00root root 0000000 0000000 package entities
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/2020-08-04/table/tables/ 0000775 0000000 0000000 00000000000 14232154237 0020444 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/2020-08-04/table/tables/README.md 0000664 0000000 0000000 00000001550 14232154237 0021724 0 ustar 00root root 0000000 0000000 ## Table Storage Tables SDK for API version 2020-08-04
This package allows you to interact with the Tables Table Storage API
### Supported Authorizers
* SharedKeyLite (Table)
### Example Usage
```go
package main
import (
"context"
"fmt"
"time"
"github.com/Azure/go-autorest/autorest"
"github.com/tombuildsstuff/giovanni/storage/2020-08-04/table/tables"
)
func Example() error {
accountName := "storageaccount1"
storageAccountKey := "ABC123...."
tableName := "mytable"
storageAuth := autorest.NewSharedKeyLiteTableAuthorizer(accountName, storageAccountKey)
tablesClient := tables.New()
tablesClient.Client.Authorizer = storageAuth
ctx := context.TODO()
if _, err := tablesClient.Insert(ctx, accountName, tableName); err != nil {
return fmt.Errorf("Error creating Table: %s", err)
}
return nil
}
``` giovanni-0.20.0/storage/2020-08-04/table/tables/acl_get.go 0000664 0000000 0000000 00000005654 14232154237 0022403 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetACLResult struct {
autorest.Response
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
}
// GetACL returns the Access Control List for the specified Table
func (client Client) GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "GetACL", "`tableName` cannot be an empty string.")
}
req, err := client.GetACLPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", nil, "Failure preparing request")
return
}
resp, err := client.GetACLSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure sending request")
return
}
result, err = client.GetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "GetACL", resp, "Failure responding to request")
return
}
return
}
// GetACLPreparer prepares the GetACL request.
func (client Client) GetACLPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// GetACLSender sends the GetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) GetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// GetACLResponder handles the response to the GetACL request. The method always
// closes the http.Response Body.
func (client Client) GetACLResponder(resp *http.Response) (result GetACLResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingXML(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/tables/acl_set.go 0000664 0000000 0000000 00000006062 14232154237 0022411 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"encoding/xml"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type setAcl struct {
SignedIdentifiers []SignedIdentifier `xml:"SignedIdentifier"`
XMLName xml.Name `xml:"SignedIdentifiers"`
}
// SetACL sets the specified Access Control List for the specified Table
func (client Client) SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "SetACL", "`tableName` cannot be an empty string.")
}
req, err := client.SetACLPreparer(ctx, accountName, tableName, acls)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", nil, "Failure preparing request")
return
}
resp, err := client.SetACLSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure sending request")
return
}
result, err = client.SetACLResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "SetACL", resp, "Failure responding to request")
return
}
return
}
// SetACLPreparer prepares the SetACL request.
func (client Client) SetACLPreparer(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
queryParameters := map[string]interface{}{
"comp": autorest.Encode("query", "acl"),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
}
input := setAcl{
SignedIdentifiers: acls,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/xml; charset=utf-8"),
autorest.AsPut(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/{tableName}", pathParameters),
autorest.WithQueryParameters(queryParameters),
autorest.WithHeaders(headers),
autorest.WithXML(&input))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// SetACLSender sends the SetACL request. The method will close the
// http.Response Body if it receives an error.
func (client Client) SetACLSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// SetACLResponder handles the response to the SetACL request. The method always
// closes the http.Response Body.
func (client Client) SetACLResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/tables/api.go 0000664 0000000 0000000 00000001417 14232154237 0021547 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"github.com/Azure/go-autorest/autorest"
)
type StorageTable interface {
Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
GetACL(ctx context.Context, accountName, tableName string) (result GetACLResult, err error)
Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error)
GetResourceID(accountName, tableName string) string
Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error)
SetACL(ctx context.Context, accountName, tableName string, acls []SignedIdentifier) (result autorest.Response, err error)
}
giovanni-0.20.0/storage/2020-08-04/table/tables/client.go 0000664 0000000 0000000 00000001126 14232154237 0022251 0 ustar 00root root 0000000 0000000 package tables
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// Client is the base client for Table Storage Shares.
type Client struct {
autorest.Client
BaseURI string
}
// New creates an instance of the Client client.
func New() Client {
return NewWithEnvironment(azure.PublicCloud)
}
// NewWithEnvironment creates an instance of the Client client.
func NewWithEnvironment(environment azure.Environment) Client {
return Client{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: environment.StorageEndpointSuffix,
}
}
giovanni-0.20.0/storage/2020-08-04/table/tables/create.go 0000664 0000000 0000000 00000005571 14232154237 0022246 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type createTableRequest struct {
TableName string `json:"TableName"`
}
// Create creates a new table in the storage account.
func (client Client) Create(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Create", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Create", "`tableName` cannot be an empty string.")
}
req, err := client.CreatePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", nil, "Failure preparing request")
return
}
resp, err := client.CreateSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure sending request")
return
}
result, err = client.CreateResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Create", resp, "Failure responding to request")
return
}
return
}
// CreatePreparer prepares the Create request.
func (client Client) CreatePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
headers := map[string]interface{}{
"x-ms-version": APIVersion,
// NOTE: we could support returning metadata here, but it doesn't appear to be directly useful
// vs making a request using the Get methods as-necessary?
"Accept": "application/json;odata=nometadata",
"Prefer": "return-no-content",
}
body := createTableRequest{
TableName: tableName,
}
preparer := autorest.CreatePreparer(
autorest.AsContentType("application/json"),
autorest.AsPost(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithJSON(body),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// CreateSender sends the Create request. The method will close the
// http.Response Body if it receives an error.
func (client Client) CreateSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// CreateResponder handles the response to the Create request. The method always
// closes the http.Response Body.
func (client Client) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/tables/delete.go 0000664 0000000 0000000 00000005260 14232154237 0022240 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Delete deletes the specified table and any data it contains.
func (client Client) Delete(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Delete", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Delete", "`tableName` cannot be an empty string.")
}
req, err := client.DeletePreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", nil, "Failure preparing request")
return
}
resp, err := client.DeleteSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure sending request")
return
}
result, err = client.DeleteResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Delete", resp, "Failure responding to request")
return
}
return
}
// DeletePreparer prepares the Delete request.
func (client Client) DeletePreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsDelete(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// DeleteSender sends the Delete request. The method will close the
// http.Response Body if it receives an error.
func (client Client) DeleteSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// DeleteResponder handles the response to the Delete request. The method always
// closes the http.Response Body.
func (client Client) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusNoContent),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/tables/exists.go 0000664 0000000 0000000 00000005543 14232154237 0022321 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// Exists checks that the specified table exists
func (client Client) Exists(ctx context.Context, accountName, tableName string) (result autorest.Response, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Exists", "`accountName` cannot be an empty string.")
}
if tableName == "" {
return result, validation.NewError("tables.Client", "Exists", "`tableName` cannot be an empty string.")
}
req, err := client.ExistsPreparer(ctx, accountName, tableName)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", nil, "Failure preparing request")
return
}
resp, err := client.ExistsSender(req)
if err != nil {
result = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure sending request")
return
}
result, err = client.ExistsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Exists", resp, "Failure responding to request")
return
}
return
}
// ExistsPreparer prepares the Exists request.
func (client Client) ExistsPreparer(ctx context.Context, accountName, tableName string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"tableName": autorest.Encode("path", tableName),
}
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": "application/json;odata=nometadata",
}
// NOTE: whilst the API documentation says that API Version is Optional
// apparently specifying it causes an "invalid content type" to always be returned
// as such we omit it here :shrug:
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.AsContentType("application/json"),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPathParameters("/Tables('{tableName}')", pathParameters),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// ExistsSender sends the Exists request. The method will close the
// http.Response Body if it receives an error.
func (client Client) ExistsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// ExistsResponder handles the response to the Exists request. The method always
// closes the http.Response Body.
func (client Client) ExistsResponder(resp *http.Response) (result autorest.Response, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByClosing())
result = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/tables/lifecycle_test.go 0000664 0000000 0000000 00000007234 14232154237 0023777 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"log"
"testing"
"github.com/Azure/azure-sdk-for-go/profiles/latest/storage/mgmt/storage"
"github.com/tombuildsstuff/giovanni/storage/internal/auth"
"github.com/tombuildsstuff/giovanni/testhelpers"
)
var _ StorageTable = Client{}
func TestTablesLifecycle(t *testing.T) {
client, err := testhelpers.Build(t)
if err != nil {
t.Fatal(err)
}
ctx := context.TODO()
resourceGroup := fmt.Sprintf("acctestrg-%d", testhelpers.RandomInt())
accountName := fmt.Sprintf("acctestsa%s", testhelpers.RandomString())
tableName := fmt.Sprintf("table%d", testhelpers.RandomInt())
testData, err := client.BuildTestResources(ctx, resourceGroup, accountName, storage.KindStorage)
if err != nil {
t.Fatal(err)
}
defer client.DestroyTestResources(ctx, resourceGroup, accountName)
storageAuth := auth.NewSharedKeyLiteTableAuthorizer(accountName, testData.StorageAccountKey)
tablesClient := NewWithEnvironment(client.Environment)
tablesClient.Client = client.PrepareWithAuthorizer(tablesClient.Client, storageAuth)
t.Logf("[DEBUG] Creating Table..")
if _, err := tablesClient.Create(ctx, accountName, tableName); err != nil {
t.Fatalf("Error creating Table %q: %s", tableName, err)
}
// first look it up directly and confirm it's there
t.Logf("[DEBUG] Checking if Table exists..")
if _, err := tablesClient.Exists(ctx, accountName, tableName); err != nil {
t.Fatalf("Error checking if Table %q exists: %s", tableName, err)
}
// then confirm it exists in the Query too
t.Logf("[DEBUG] Querying for Tables..")
result, err := tablesClient.Query(ctx, accountName, NoMetaData)
if err != nil {
t.Fatalf("Error retrieving Tables: %s", err)
}
found := false
for _, v := range result.Tables {
log.Printf("[DEBUG] Table: %q", v.TableName)
if v.TableName == tableName {
found = true
}
}
if !found {
t.Fatalf("%q was not found in the Query response!", tableName)
}
t.Logf("[DEBUG] Setting ACL's for Table %q..", tableName)
acls := []SignedIdentifier{
{
Id: "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=",
AccessPolicy: AccessPolicy{
Permission: "raud",
Start: "2020-11-26T08:49:37.0000000Z",
Expiry: "2020-11-27T08:49:37.0000000Z",
},
},
}
if _, err := tablesClient.SetACL(ctx, accountName, tableName, acls); err != nil {
t.Fatalf("Error setting ACLs: %s", err)
}
t.Logf("[DEBUG] Retrieving ACL's for Table %q..", tableName)
retrievedACLs, err := tablesClient.GetACL(ctx, accountName, tableName)
if err != nil {
t.Fatalf("Error retrieving ACLs: %s", err)
}
if len(retrievedACLs.SignedIdentifiers) != len(acls) {
t.Fatalf("Expected %d but got %q ACLs", len(retrievedACLs.SignedIdentifiers), len(acls))
}
for i, retrievedAcl := range retrievedACLs.SignedIdentifiers {
expectedAcl := acls[i]
if retrievedAcl.Id != expectedAcl.Id {
t.Fatalf("Expected ID to be %q but got %q", retrievedAcl.Id, expectedAcl.Id)
}
if retrievedAcl.AccessPolicy.Start != expectedAcl.AccessPolicy.Start {
t.Fatalf("Expected Start to be %q but got %q", retrievedAcl.AccessPolicy.Start, expectedAcl.AccessPolicy.Start)
}
if retrievedAcl.AccessPolicy.Expiry != expectedAcl.AccessPolicy.Expiry {
t.Fatalf("Expected Expiry to be %q but got %q", retrievedAcl.AccessPolicy.Expiry, expectedAcl.AccessPolicy.Expiry)
}
if retrievedAcl.AccessPolicy.Permission != expectedAcl.AccessPolicy.Permission {
t.Fatalf("Expected Permission to be %q but got %q", retrievedAcl.AccessPolicy.Permission, expectedAcl.AccessPolicy.Permission)
}
}
t.Logf("[DEBUG] Deleting Table %q..", tableName)
if _, err := tablesClient.Delete(ctx, accountName, tableName); err != nil {
t.Fatalf("Error deleting %q: %s", tableName, err)
}
}
giovanni-0.20.0/storage/2020-08-04/table/tables/models.go 0000664 0000000 0000000 00000001324 14232154237 0022256 0 ustar 00root root 0000000 0000000 package tables
type MetaDataLevel string
var (
NoMetaData MetaDataLevel = "nometadata"
MinimalMetaData MetaDataLevel = "minimalmetadata"
FullMetaData MetaDataLevel = "fullmetadata"
)
type GetResultItem struct {
TableName string `json:"TableName"`
// Optional, depending on the MetaData Level
ODataType string `json:"odata.type,omitempty"`
ODataID string `json:"odata.id,omitEmpty"`
ODataEditLink string `json:"odata.editLink,omitEmpty"`
}
type SignedIdentifier struct {
Id string `xml:"Id"`
AccessPolicy AccessPolicy `xml:"AccessPolicy"`
}
type AccessPolicy struct {
Start string `xml:"Start"`
Expiry string `xml:"Expiry"`
Permission string `xml:"Permission"`
}
giovanni-0.20.0/storage/2020-08-04/table/tables/query.go 0000664 0000000 0000000 00000005430 14232154237 0022142 0 ustar 00root root 0000000 0000000 package tables
import (
"context"
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/validation"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
type GetResult struct {
autorest.Response
MetaData string `json:"odata.metadata,omitempty"`
Tables []GetResultItem `json:"value"`
}
// Query returns a list of tables under the specified account.
func (client Client) Query(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (result GetResult, err error) {
if accountName == "" {
return result, validation.NewError("tables.Client", "Query", "`accountName` cannot be an empty string.")
}
req, err := client.QueryPreparer(ctx, accountName, metaDataLevel)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", nil, "Failure preparing request")
return
}
resp, err := client.QuerySender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure sending request")
return
}
result, err = client.QueryResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "tables.Client", "Query", resp, "Failure responding to request")
return
}
return
}
// QueryPreparer prepares the Query request.
func (client Client) QueryPreparer(ctx context.Context, accountName string, metaDataLevel MetaDataLevel) (*http.Request, error) {
// NOTE: whilst this supports ContinuationTokens and 'Top'
// it appears that 'Skip' returns a '501 Not Implemented'
// as such, we intentionally don't support those right now
headers := map[string]interface{}{
"x-ms-version": APIVersion,
"Accept": fmt.Sprintf("application/json;odata=%s", metaDataLevel),
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(endpoints.GetTableEndpoint(client.BaseURI, accountName)),
autorest.WithPath("/Tables"),
autorest.WithHeaders(headers))
return preparer.Prepare((&http.Request{}).WithContext(ctx))
}
// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client Client) QuerySender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req,
azure.DoRetryWithRegistration(client.Client))
}
// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client Client) QueryResponder(resp *http.Response) (result GetResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
giovanni-0.20.0/storage/2020-08-04/table/tables/resource_id.go 0000664 0000000 0000000 00000003112 14232154237 0023273 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"net/url"
"strings"
"github.com/tombuildsstuff/giovanni/storage/internal/endpoints"
)
// GetResourceID returns the Resource ID for the given Table
// This can be useful when, for example, you're using this as a unique identifier
func (client Client) GetResourceID(accountName, tableName string) string {
domain := endpoints.GetTableEndpoint(client.BaseURI, accountName)
return fmt.Sprintf("%s/Tables('%s')", domain, tableName)
}
type ResourceID struct {
AccountName string
TableName string
}
// ParseResourceID parses the Resource ID and returns an object which
// can be used to interact with the Table within the specified Storage Account
func ParseResourceID(id string) (*ResourceID, error) {
// example: https://foo.table.core.windows.net/Table('foo')
if id == "" {
return nil, fmt.Errorf("`id` was empty")
}
uri, err := url.Parse(id)
if err != nil {
return nil, fmt.Errorf("Error parsing ID as a URL: %s", err)
}
accountName, err := endpoints.GetAccountNameFromEndpoint(uri.Host)
if err != nil {
return nil, fmt.Errorf("Error parsing Account Name: %s", err)
}
// assume there a `Table('')`
path := strings.TrimPrefix(uri.Path, "/")
if !strings.HasPrefix(path, "Tables('") || !strings.HasSuffix(path, "')") {
return nil, fmt.Errorf("Expected the Table Name to be in the format `Tables('name')` but got %q", path)
}
// strip off the `Table('')`
tableName := strings.TrimPrefix(uri.Path, "/Tables('")
tableName = strings.TrimSuffix(tableName, "')")
return &ResourceID{
AccountName: *accountName,
TableName: tableName,
}, nil
}
giovanni-0.20.0/storage/2020-08-04/table/tables/resource_id_test.go 0000664 0000000 0000000 00000004010 14232154237 0024330 0 ustar 00root root 0000000 0000000 package tables
import (
"testing"
"github.com/Azure/go-autorest/autorest/azure"
)
func TestGetResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Expected string
}{
{
Environment: azure.ChinaCloud,
Expected: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Expected: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Expected: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Expected: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
c := NewWithEnvironment(v.Environment)
actual := c.GetResourceID("account1", "table1")
if actual != v.Expected {
t.Fatalf("Expected the Resource ID to be %q but got %q", v.Expected, actual)
}
}
}
func TestParseResourceID(t *testing.T) {
testData := []struct {
Environment azure.Environment
Input string
}{
{
Environment: azure.ChinaCloud,
Input: "https://account1.table.core.chinacloudapi.cn/Tables('table1')",
},
{
Environment: azure.GermanCloud,
Input: "https://account1.table.core.cloudapi.de/Tables('table1')",
},
{
Environment: azure.PublicCloud,
Input: "https://account1.table.core.windows.net/Tables('table1')",
},
{
Environment: azure.USGovernmentCloud,
Input: "https://account1.table.core.usgovcloudapi.net/Tables('table1')",
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing Environment %q", v.Environment.Name)
actual, err := ParseResourceID(v.Input)
if err != nil {
t.Fatal(err)
}
if actual.AccountName != "account1" {
t.Fatalf("Expected Account Name to be `account1` but got %q", actual.AccountName)
}
if actual.TableName != "table1" {
t.Fatalf("Expected Table Name to be `table1` but got %q", actual.TableName)
}
}
}
giovanni-0.20.0/storage/2020-08-04/table/tables/version.go 0000664 0000000 0000000 00000000464 14232154237 0022464 0 ustar 00root root 0000000 0000000 package tables
import (
"fmt"
"github.com/tombuildsstuff/giovanni/version"
)
// APIVersion is the version of the API used for all Storage API Operations
const APIVersion = "2020-08-04"
func UserAgent() string {
return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion)
}
giovanni-0.20.0/storage/accesscontrol/ 0000775 0000000 0000000 00000000000 14232154237 0017714 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/accesscontrol/ace.go 0000664 0000000 0000000 00000005413 14232154237 0020776 0 ustar 00root root 0000000 0000000 package accesscontrol
import (
"fmt"
"regexp"
"strings"
"github.com/google/uuid"
)
type TagType string
const (
TagTypeUser TagType = "user"
TagTypeGroup TagType = "group"
TagTypeMask TagType = "mask"
TagTypeOther TagType = "other"
)
// ACE is roughly modelled on https://linux.die.net/man/5/acl
// Have collapsed ACL_USER_OBJ to be TagType of user with a nil Qualifier
type ACE struct {
IsDefault bool
TagType TagType
TagQualifier *uuid.UUID
Permissions string // TODO break the rwx into permission flags?
}
var permissionsRegex *regexp.Regexp
func init() {
permissionsRegex = regexp.MustCompile("[r-][w-][x-]")
}
// ValidateACEPermissions checks the format of the ACE permission string. Returns nil on success.
func ValidateACEPermissions(permissions string) error {
if !permissionsRegex.MatchString(permissions) {
return fmt.Errorf("Permissions must be of the form [r-][w-][x-]")
}
return nil
}
// Validate checks the formatting and combination of values in the ACE. Returns nil on success
func (ace *ACE) Validate() error {
switch ace.TagType {
case TagTypeMask, TagTypeOther:
if ace.TagQualifier != nil {
return fmt.Errorf("TagQualifier cannot be set for 'mask' or 'other' TagTypes")
}
}
if err := ValidateACEPermissions(ace.Permissions); err != nil {
return err
}
if err := validateTagType(ace.TagType); err != nil {
return err
}
return nil
}
// ParseACE parses an ACE string and returns the ACE
func ParseACE(input string) (ACE, error) {
ace := ACE{}
parts := strings.Split(input, ":")
if len(parts) == 4 {
if parts[0] == "default" {
ace.IsDefault = true
parts = parts[1:]
} else {
return ACE{}, fmt.Errorf("When specifying a 4-part ACE the first part must be 'default'")
}
}
if len(parts) != 3 {
return ACE{}, fmt.Errorf("ACE string should have either 3 or 4 parts")
}
ace.TagType = TagType(parts[0])
qualiferString := parts[1]
if qualiferString != "" {
qualifier, err := uuid.Parse(qualiferString)
if err != nil {
return ACE{}, fmt.Errorf("Error parsing qualifer %q: %s", qualiferString, err)
}
ace.TagQualifier = &qualifier
}
ace.Permissions = parts[2]
if err := ace.Validate(); err != nil {
return ACE{}, err
}
return ace, nil
}
// String returns the string form of the ACE - this does not check that it is valid
func (ace *ACE) String() string {
prefix := ""
if ace.IsDefault {
prefix = "default:"
}
qualifierString := ""
if ace.TagQualifier != nil {
qualifierString = ace.TagQualifier.String()
}
return fmt.Sprintf("%s%s:%s:%s", prefix, ace.TagType, qualifierString, ace.Permissions)
}
func validateTagType(tagType TagType) error {
switch tagType {
case TagTypeUser,
TagTypeGroup,
TagTypeMask,
TagTypeOther:
return nil
}
return fmt.Errorf("Unrecognized TagType: %q", tagType)
}
giovanni-0.20.0/storage/accesscontrol/ace_test.go 0000664 0000000 0000000 00000005670 14232154237 0022042 0 ustar 00root root 0000000 0000000 package accesscontrol
import (
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func TestACEValidate_WithValidACE(t *testing.T) {
ace := ACE{
TagType: TagTypeUser,
Permissions: "rwx",
}
assert.Nil(t, ace.Validate(), "Expected ACE to Validate successfully")
}
func TestACEValidate_WithACEInvalidPermisions(t *testing.T) {
ace := ACE{
TagType: TagTypeUser,
Permissions: "awx",
}
assert.EqualError(t, ace.Validate(), "Permissions must be of the form [r-][w-][x-]")
}
func TestACEValidate_WithACEQualifierSetForMask(t *testing.T) {
qualifier := uuid.MustParse("ba4662cb-995c-479d-8f7c-a1b3d8ae05a9")
ace := ACE{
TagType: TagTypeMask,
TagQualifier: &qualifier,
Permissions: "rwx",
}
assert.EqualError(t, ace.Validate(), "TagQualifier cannot be set for 'mask' or 'other' TagTypes")
}
func TestACEParse_WithValidDefault(t *testing.T) {
ace, err := ParseACE("default:user:22edd3d8-9253-4463-b8f8-442ebe33b622:rwx")
assert.NoError(t, err)
assert.Equal(t, true, ace.IsDefault, "Expected default")
assert.Equal(t, TagTypeUser, ace.TagType)
assert.Equal(t, "22edd3d8-9253-4463-b8f8-442ebe33b622", ace.TagQualifier.String())
assert.Equal(t, "rwx", ace.Permissions)
}
func TestACEParse_WithValidNonDefault(t *testing.T) {
ace, err := ParseACE("user:885d0d94-9ecb-4e0d-8581-781b56d27b10:rwx")
assert.NoError(t, err)
assert.Equal(t, false, ace.IsDefault, "Expected non-default")
assert.Equal(t, TagTypeUser, ace.TagType)
assert.Equal(t, "885d0d94-9ecb-4e0d-8581-781b56d27b10", ace.TagQualifier.String())
assert.Equal(t, "rwx", ace.Permissions)
}
func TestACEParse_WithInvalid4Part(t *testing.T) {
_, err := ParseACE("test:::")
assert.EqualError(t, err, "When specifying a 4-part ACE the first part must be 'default'")
}
func TestACEParse_WithInvalidTagType(t *testing.T) {
_, err := ParseACE("wibble::rwx")
assert.EqualError(t, err, "Unrecognized TagType: \"wibble\"")
}
func TestACEParse_WithInvalidNumberOfParts(t *testing.T) {
_, err := ParseACE("user:rwx")
assert.EqualError(t, err, "ACE string should have either 3 or 4 parts")
}
func TestACEParse_WithInvalidQualifier(t *testing.T) {
_, err := ParseACE("user:wibble94-9ecb-4e0d-8581-781b56d27b10:rwx")
assert.EqualError(t, err, "Error parsing qualifer \"wibble94-9ecb-4e0d-8581-781b56d27b10\": invalid UUID format")
}
func TestACEString_WithDefault(t *testing.T) {
qualifier := uuid.MustParse("ba4662cb-995c-479d-8f7c-a1b3d8ae05a9")
ace := ACE{
IsDefault: true,
TagType: TagTypeUser,
TagQualifier: &qualifier,
Permissions: "r-x",
}
assert.Equal(t, "default:user:ba4662cb-995c-479d-8f7c-a1b3d8ae05a9:r-x", ace.String())
}
func TestACEString_WithNonDefault(t *testing.T) {
qualifier := uuid.MustParse("ba4662cb-995c-479d-8f7c-a1b3d8ae05a9")
ace := ACE{
IsDefault: false,
TagType: TagTypeGroup,
TagQualifier: &qualifier,
Permissions: "rw-",
}
assert.Equal(t, "group:ba4662cb-995c-479d-8f7c-a1b3d8ae05a9:rw-", ace.String())
}
giovanni-0.20.0/storage/accesscontrol/acl.go 0000664 0000000 0000000 00000002021 14232154237 0020775 0 ustar 00root root 0000000 0000000 package accesscontrol
import (
"strings"
)
type ACL struct {
Entries []ACE
}
// Validate checks the ACL. Returns nil on success
func (acl *ACL) Validate() error {
// TODO
// - check each user/group is only listed once (per default/non-default)
for _, v := range acl.Entries {
if err := v.Validate(); err != nil {
return err
}
}
return nil
}
// ParseACL parses an ACL string
func ParseACL(input string) (ACL, error) {
aceStrings := strings.Split(input, ",")
entries := make([]ACE, len(aceStrings))
for i := 0; i < len(aceStrings); i++ {
aceString := aceStrings[i]
entry, err := ParseACE(aceString)
if err != nil {
return ACL{}, err
}
entries[i] = entry
}
return ACL{Entries: entries}, nil
}
// String returns the string form of the ACL - this does not check that it is valid
func (acl *ACL) String() string {
aceStrings := make([]string, len(acl.Entries))
for i := 0; i < len(acl.Entries); i++ {
ace := acl.Entries[i]
aceStrings[i] = ace.String()
}
return strings.Join(aceStrings, ",")
}
giovanni-0.20.0/storage/accesscontrol/acl_test.go 0000664 0000000 0000000 00000003350 14232154237 0022042 0 ustar 00root root 0000000 0000000 package accesscontrol
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestACLValidate_WithValidACL(t *testing.T) {
acl := ACL{
Entries: []ACE{
{
TagType: TagTypeUser,
Permissions: "rwx",
},
{
TagType: TagTypeGroup,
Permissions: "r-x",
},
{
TagType: TagTypeOther,
Permissions: "---",
},
},
}
assert.Nil(t, acl.Validate(), "Expected ACE to Validate successfully")
}
func TestACLValidate_WithInvalidACL(t *testing.T) {
acl := ACL{
Entries: []ACE{
{
TagType: TagType("wibble"),
Permissions: "rwx",
},
{
TagType: TagTypeGroup,
Permissions: "r-x",
},
{
TagType: TagTypeOther,
Permissions: "---",
},
},
}
assert.Error(t, acl.Validate(), "Expected ACE to fail to Validate")
}
func TestACLString(t *testing.T) {
acl := ACL{
Entries: []ACE{
{
TagType: TagTypeUser,
Permissions: "rwx",
},
{
TagType: TagTypeGroup,
Permissions: "r-x",
},
{
TagType: TagTypeOther,
Permissions: "---",
},
},
}
assert.Equal(t, "user::rwx,group::r-x,other::---", acl.String())
}
func TestACLParse_WithValidACL(t *testing.T) {
expected := ACL{
Entries: []ACE{
{
TagType: TagTypeUser,
Permissions: "rwx",
},
{
TagType: TagTypeGroup,
Permissions: "r-x",
},
{
TagType: TagTypeOther,
Permissions: "---",
},
},
}
acl, err := ParseACL("user::rwx,group::r-x,other::---")
assert.Nil(t, err, "Expected ACE to parse successfully")
assert.Equal(t, expected, acl)
}
func TestACLParse_WithInvalidACL(t *testing.T) {
_, err := ParseACL("user:rwx,group::r-x,other::---")
assert.EqualError(t, err, "ACE string should have either 3 or 4 parts")
}
giovanni-0.20.0/storage/internal/ 0000775 0000000 0000000 00000000000 14232154237 0016666 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/internal/auth/ 0000775 0000000 0000000 00000000000 14232154237 0017627 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/internal/auth/TODO.md 0000664 0000000 0000000 00000000134 14232154237 0020714 0 ustar 00root root 0000000 0000000 TODO: this can be removed once https://github.com/Azure/go-autorest/pull/416 has been merged giovanni-0.20.0/storage/internal/auth/authorizer_shared_key_lite.go 0000664 0000000 0000000 00000006143 14232154237 0025571 0 ustar 00root root 0000000 0000000 package auth
import (
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
)
// SharedKeyLiteAuthorizer implements an authorization for Shared Key Lite
// this can be used for interaction with Blob, File and Queue Storage Endpoints
type SharedKeyLiteAuthorizer struct {
storageAccountName string
storageAccountKey string
}
// NewSharedKeyLiteAuthorizer crates a SharedKeyLiteAuthorizer using the given credentials
func NewSharedKeyLiteAuthorizer(accountName, accountKey string) *SharedKeyLiteAuthorizer {
return &SharedKeyLiteAuthorizer{
storageAccountName: accountName,
storageAccountKey: accountKey,
}
}
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
// value is "SharedKeyLite " followed by the computed key.
// This can be used for the Blob, Queue, and File Services
//
// from: https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key
// You may use Shared Key Lite authorization to authorize a request made against the
// 2009-09-19 version and later of the Blob and Queue services,
// and version 2014-02-14 and later of the File services.
func (skl *SharedKeyLiteAuthorizer) WithAuthorization() autorest.PrepareDecorator {
return func(p autorest.Preparer) autorest.Preparer {
return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
r, err := p.Prepare(r)
if err != nil {
return r, err
}
key, err := buildSharedKeyLite(skl.storageAccountName, skl.storageAccountKey, r)
if err != nil {
return r, err
}
sharedKeyHeader := formatSharedKeyLiteAuthorizationHeader(skl.storageAccountName, *key)
return autorest.Prepare(r, autorest.WithHeader(HeaderAuthorization, sharedKeyHeader))
})
}
}
func buildSharedKeyLite(accountName, storageAccountKey string, r *http.Request) (*string, error) {
// first ensure the relevant headers are configured
prepareHeadersForRequest(r)
sharedKey, err := computeSharedKeyLite(r.Method, r.URL.String(), accountName, r.Header)
if err != nil {
return nil, err
}
// we then need to HMAC that value
hmacdValue := hmacValue(storageAccountKey, *sharedKey)
return &hmacdValue, nil
}
// computeSharedKeyLite computes the Shared Key Lite required for Storage Authentication
// NOTE: this function assumes that the `x-ms-date` field is set
func computeSharedKeyLite(verb, url string, accountName string, headers http.Header) (*string, error) {
canonicalizedResource, err := buildCanonicalizedResource(url, accountName)
if err != nil {
return nil, err
}
canonicalizedHeaders := buildCanonicalizedHeader(headers)
canonicalizedString := buildCanonicalizedStringForSharedKeyLite(verb, headers, canonicalizedHeaders, *canonicalizedResource)
return &canonicalizedString, nil
}
func buildCanonicalizedStringForSharedKeyLite(verb string, headers http.Header, canonicalizedHeaders, canonicalizedResource string) string {
return strings.Join([]string{
verb,
headers.Get(HeaderContentMD5), // TODO: this appears to always be empty?
headers.Get(HeaderContentType),
"", // date should be nil, apparently :shrug:
canonicalizedHeaders,
canonicalizedResource,
}, "\n")
}
giovanni-0.20.0/storage/internal/auth/authorizer_shared_key_lite_table.go 0000664 0000000 0000000 00000005572 14232154237 0026745 0 ustar 00root root 0000000 0000000 package auth
import (
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
)
// SharedKeyLiteTableAuthorizer implements an authorization for Shared Key Lite
// this can be used for interaction with Table Storage Endpoints
type SharedKeyLiteTableAuthorizer struct {
storageAccountName string
storageAccountKey string
}
// NewSharedKeyLiteAuthorizer crates a SharedKeyLiteAuthorizer using the given credentials
func NewSharedKeyLiteTableAuthorizer(accountName, accountKey string) *SharedKeyLiteTableAuthorizer {
return &SharedKeyLiteTableAuthorizer{
storageAccountName: accountName,
storageAccountKey: accountKey,
}
}
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
// value is "SharedKeyLite " followed by the computed key.
// This can be used for the Blob, Queue, and File Services
//
// from: https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key
// You may use Shared Key Lite authorization to authorize a request made against the
// 2009-09-19 version and later of the Blob and Queue services,
// and version 2014-02-14 and later of the File services.
func (skl *SharedKeyLiteTableAuthorizer) WithAuthorization() autorest.PrepareDecorator {
return func(p autorest.Preparer) autorest.Preparer {
return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
r, err := p.Prepare(r)
if err != nil {
return r, err
}
key, err := buildSharedKeyLiteTable(skl.storageAccountName, skl.storageAccountKey, r)
if err != nil {
return r, err
}
sharedKeyHeader := formatSharedKeyLiteAuthorizationHeader(skl.storageAccountName, *key)
return autorest.Prepare(r, autorest.WithHeader(HeaderAuthorization, sharedKeyHeader))
})
}
}
func buildSharedKeyLiteTable(accountName, storageAccountKey string, r *http.Request) (*string, error) {
// first ensure the relevant headers are configured
prepareHeadersForRequest(r)
sharedKey, err := computeSharedKeyLiteTable(r.URL.String(), accountName, r.Header)
if err != nil {
return nil, err
}
// we then need to HMAC that value
hmacdValue := hmacValue(storageAccountKey, *sharedKey)
return &hmacdValue, nil
}
// computeSharedKeyLite computes the Shared Key Lite required for Storage Authentication
// NOTE: this function assumes that the `x-ms-date` field is set
func computeSharedKeyLiteTable(url string, accountName string, headers http.Header) (*string, error) {
dateHeader := headers.Get("x-ms-date")
canonicalizedResource, err := buildCanonicalizedResource(url, accountName)
if err != nil {
return nil, err
}
canonicalizedString := buildCanonicalizedStringForSharedKeyLiteTable(*canonicalizedResource, dateHeader)
return &canonicalizedString, nil
}
func buildCanonicalizedStringForSharedKeyLiteTable(canonicalizedResource, dateHeader string) string {
return strings.Join([]string{
dateHeader,
canonicalizedResource,
}, "\n")
}
giovanni-0.20.0/storage/internal/auth/authorizer_shared_key_lite_test.go 0000664 0000000 0000000 00000001722 14232154237 0026626 0 ustar 00root root 0000000 0000000 package auth
import (
"testing"
)
func TestBuildCanonicalizedStringForSharedKeyLite(t *testing.T) {
testData := []struct {
name string
headers map[string][]string
canonicalizedHeaders string
canonicalizedResource string
verb string
expected string
}{
{
name: "completed",
verb: "NOM",
headers: map[string][]string{
"Content-MD5": {"abc123"},
"Content-Type": {"vnd/panda-pops+v1"},
},
canonicalizedHeaders: "all-the-headers",
canonicalizedResource: "all-the-resources",
expected: "NOM\n\nvnd/panda-pops+v1\n\nall-the-headers\nall-the-resources",
},
}
for _, test := range testData {
t.Logf("Test: %q", test.name)
actual := buildCanonicalizedStringForSharedKeyLite(test.verb, test.headers, test.canonicalizedHeaders, test.canonicalizedResource)
if actual != test.expected {
t.Fatalf("Expected %q but got %q", test.expected, actual)
}
}
}
giovanni-0.20.0/storage/internal/auth/consts.go 0000664 0000000 0000000 00000001302 14232154237 0021463 0 ustar 00root root 0000000 0000000 package auth
var (
HeaderAuthorization = "Authorization"
HeaderContentLength = "Content-Length"
HeaderContentEncoding = "Content-Encoding"
HeaderContentLanguage = "Content-Language"
HeaderContentType = "Content-Type"
HeaderContentMD5 = "Content-MD5"
HeaderIfModifiedSince = "If-Modified-Since"
HeaderIfMatch = "If-Match"
HeaderIfNoneMatch = "If-None-Match"
HeaderIfUnmodifiedSince = "If-Unmodified-Since"
HeaderMSDate = "X-Ms-Date"
HeaderRange = "Range"
StorageEmulatorAccountName = "devstoreaccount1"
StorageEmulatorAccountKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
)
giovanni-0.20.0/storage/internal/auth/helpers.go 0000664 0000000 0000000 00000007020 14232154237 0021617 0 ustar 00root root 0000000 0000000 package auth
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"time"
)
// NOTE: this all came from the Azure SDK for Go, but has been refactored to aid creating a Preparer.
// buildCanonicalizedHeader builds the Canonicalized Header required to sign Storage Requests
func buildCanonicalizedHeader(headers http.Header) string {
cm := make(map[string]string)
for k, v := range headers {
headerName := strings.TrimSpace(strings.ToLower(k))
if strings.HasPrefix(headerName, "x-ms-") {
cm[headerName] = v[0]
}
}
if len(cm) == 0 {
return ""
}
var keys []string
for key := range cm {
keys = append(keys, key)
}
sort.Strings(keys)
ch := bytes.NewBufferString("")
for _, key := range keys {
ch.WriteString(key)
ch.WriteRune(':')
ch.WriteString(cm[key])
ch.WriteRune('\n')
}
return strings.TrimSuffix(string(ch.Bytes()), "\n")
}
// buildCanonicalizedResource builds the Canonical Resource required for to sign Storage Account requests
func buildCanonicalizedResource(uri, accountName string) (*string, error) {
u, err := url.Parse(uri)
if err != nil {
return nil, err
}
cr := bytes.NewBufferString("")
if accountName != StorageEmulatorAccountName {
cr.WriteString("/")
cr.WriteString(primaryStorageAccountName(accountName))
}
if len(u.Path) > 0 {
// Any portion of the CanonicalizedResource string that is derived from
// the resource's URI should be encoded exactly as it is in the URI.
// -- https://msdn.microsoft.com/en-gb/library/azure/dd179428.aspx
cr.WriteString(u.EscapedPath())
}
// TODO: replace this with less of a hack
if comp := u.Query().Get("comp"); comp != "" {
cr.WriteString(fmt.Sprintf("?comp=%s", comp))
}
out := string(cr.Bytes())
return &out, nil
}
func formatSharedKeyLiteAuthorizationHeader(accountName, key string) string {
canonicalizedAccountName := primaryStorageAccountName(accountName)
return fmt.Sprintf("SharedKeyLite %s:%s", canonicalizedAccountName, key)
}
// hmacValue base-64 decodes the storageAccountKey, then signs the string with it
// as outlined here: https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key
func hmacValue(storageAccountKey, canonicalizedString string) string {
key, err := base64.StdEncoding.DecodeString(storageAccountKey)
if err != nil {
return ""
}
encr := hmac.New(sha256.New, []byte(key))
encr.Write([]byte(canonicalizedString))
return base64.StdEncoding.EncodeToString(encr.Sum(nil))
}
// prepareHeadersForRequest prepares a request so that it can be signed
// by ensuring the `date` and `x-ms-date` headers are set
func prepareHeadersForRequest(r *http.Request) {
if r.Header == nil {
r.Header = http.Header{}
}
date := time.Now().UTC().Format(http.TimeFormat)
// a date must be set, X-Ms-Date should be used when both are set; but let's set both for completeness
r.Header.Set("date", date)
r.Header.Set("x-ms-date", date)
}
// primaryStorageAccountName returns the name of the primary for a given Storage Account
func primaryStorageAccountName(input string) string {
// from https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key
// If you are accessing the secondary location in a storage account for which
// read-access geo-replication (RA-GRS) is enabled, do not include the
// -secondary designation in the authorization header.
// For authorization purposes, the account name is always the name of the primary location,
// even for secondary access.
return strings.TrimSuffix(input, "-secondary")
}
giovanni-0.20.0/storage/internal/auth/helpers_test.go 0000664 0000000 0000000 00000013357 14232154237 0022670 0 ustar 00root root 0000000 0000000 package auth
import (
"encoding/base64"
"net/http"
"testing"
)
func TestBuildCanonicalizedHeader(t *testing.T) {
testData := []struct {
Input http.Header
Expected string
}{
{
// no headers
Expected: "",
Input: map[string][]string{
"": {""},
},
},
{
// no x-ms headers
Expected: "",
Input: map[string][]string{
"panda": {"pops"},
},
},
{
// only a single x-ms header
Expected: "x-ms-panda:nom",
Input: map[string][]string{
"x-ms-panda": {"nom"},
},
},
{
// multiple x-ms headers
Expected: "x-ms-panda:nom\nx-ms-tiger:rawr",
Input: map[string][]string{
"x-ms-panda": {"nom"},
"x-ms-tiger": {"rawr"},
},
},
{
// multiple x-ms headers, out of order
Expected: "x-ms-panda:nom\nx-ms-tiger:rawr",
Input: map[string][]string{
"x-ms-tiger": {"rawr"},
"x-ms-panda": {"nom"},
},
},
{
// mixed headers (some ms, some non-ms)
Expected: "x-ms-panda:nom\nx-ms-tiger:rawr",
Input: map[string][]string{
"x-ms-tiger": {"rawr"},
"panda": {"pops"},
"x-ms-panda": {"nom"},
},
},
{
// casing
Expected: "x-ms-panda:nom\nx-ms-tiger:rawr",
Input: map[string][]string{
"X-Ms-Tiger": {"rawr"},
"X-Ms-Panda": {"nom"},
},
},
}
for _, v := range testData {
actual := buildCanonicalizedHeader(v.Input)
if actual != v.Expected {
t.Fatalf("Expected %q but got %q", v.Expected, actual)
}
}
}
func TestBuildCanonicalizedResource(t *testing.T) {
testData := []struct {
name string
accountName string
uri string
expected string
expectError bool
}{
{
name: "invalid uri",
accountName: "example",
uri: "://example.com",
expected: "",
expectError: true,
},
{
name: "storage emulator doesn't get prefix",
accountName: StorageEmulatorAccountName,
uri: "http://www.example.com/foo",
expected: "/foo",
},
{
name: "non storage emulator gets prefix",
accountName: StorageEmulatorAccountName + "test",
uri: "http://www.example.com/foo",
expected: "/" + StorageEmulatorAccountName + "test/foo",
},
{
name: "uri encoding",
accountName: "example",
uri: "",
expected: "/example%3Chello%3E",
},
{
name: "comp-arg",
accountName: "example",
uri: "/endpoint?first=true&comp=bar&second=false&third=panda",
expected: "/example/endpoint?comp=bar",
},
{
name: "arguments",
accountName: "example",
uri: "/endpoint?first=true&second=false&third=panda",
expected: "/example/endpoint",
},
}
for _, test := range testData {
t.Logf("Test %q", test.name)
actual, err := buildCanonicalizedResource(test.uri, test.accountName)
if err != nil {
if test.expectError {
continue
}
t.Fatalf("Error: %s", err)
}
if *actual != test.expected {
t.Fatalf("Expected %q but got %q", test.expected, *actual)
}
}
}
func TestFormatSharedKeyLiteAuthorizationHeader(t *testing.T) {
testData := []struct {
name string
accountName string
accountKey string
expected string
}{
{
name: "primary",
accountName: "account1",
accountKey: "examplekey",
expected: "SharedKeyLite account1:examplekey",
},
{
name: "secondary",
accountName: "account1-secondary",
accountKey: "examplekey",
expected: "SharedKeyLite account1:examplekey",
},
}
for _, test := range testData {
t.Logf("Test: %q", test.name)
actual := formatSharedKeyLiteAuthorizationHeader(test.accountName, test.accountKey)
if actual != test.expected {
t.Fatalf("Expected %q but got %q", test.expected, actual)
}
}
}
func TestHMAC(t *testing.T) {
testData := []struct {
Expected string
StorageAccountKey string
CanonicalizedString string
}{
{
// When Storage Key isn't base-64 encoded
Expected: "",
StorageAccountKey: "bar",
CanonicalizedString: "foobarzoo",
},
{
// Valid
Expected: "h5U0ATVX6SpbFX1H6GNuxIMeXXCILLoIvhflPtuQZ30=",
StorageAccountKey: base64.StdEncoding.EncodeToString([]byte("bar")),
CanonicalizedString: "foobarzoo",
},
}
for _, v := range testData {
actual := hmacValue(v.StorageAccountKey, v.CanonicalizedString)
if actual != v.Expected {
t.Fatalf("Expected %q but got %q", v.Expected, actual)
}
}
}
func TestTestPrepareHeadersForRequest(t *testing.T) {
request, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatal(err)
}
headers := []string{
"Date",
"X-Ms-Date",
}
for _, header := range headers {
existingVal := request.Header.Get(header)
if existingVal != "" {
t.Fatalf("%q had a value prior to being set: %q", header, existingVal)
}
}
prepareHeadersForRequest(request)
for _, header := range headers {
updatedVal := request.Header.Get(header)
if updatedVal == "" {
t.Fatalf("%q didn't have a value after being set: %q", header, updatedVal)
}
}
}
func TestPrepareHeadersForRequestWithNoneConfigured(t *testing.T) {
request, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatal(err)
}
request.Header = nil
prepareHeadersForRequest(request)
if request.Header == nil {
t.Fatalf("Expected `request.Header` to not be nil, but it was!")
}
}
func TestPrimaryStorageAccountName(t *testing.T) {
testData := []struct {
Expected string
Input string
}{
{
// Empty
Expected: "",
Input: "",
},
{
// Primary
Expected: "bar",
Input: "bar",
},
{
// Secondary
Expected: "bar",
Input: "bar-secondary",
},
}
for _, v := range testData {
actual := primaryStorageAccountName(v.Input)
if actual != v.Expected {
t.Fatalf("Expected %q but got %q", v.Expected, actual)
}
}
}
giovanni-0.20.0/storage/internal/endpoints/ 0000775 0000000 0000000 00000000000 14232154237 0020671 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/internal/endpoints/endpoints.go 0000664 0000000 0000000 00000002621 14232154237 0023224 0 ustar 00root root 0000000 0000000 package endpoints
import (
"fmt"
"strings"
)
func GetAccountNameFromEndpoint(endpoint string) (*string, error) {
segments := strings.Split(endpoint, ".")
if len(segments) == 0 {
return nil, fmt.Errorf("The Endpoint contained no segments")
}
return &segments[0], nil
}
// GetBlobEndpoint returns the endpoint for Blob API Operations on this storage account
func GetBlobEndpoint(baseUri string, accountName string) string {
return fmt.Sprintf("https://%s.blob.%s", accountName, baseUri)
}
// GetDataLakeStoreEndpoint returns the endpoint for Data Lake Store API Operations on this storage account
func GetDataLakeStoreEndpoint(baseUri string, accountName string) string {
return fmt.Sprintf("https://%s.dfs.%s", accountName, baseUri)
}
// GetFileEndpoint returns the endpoint for File Share API Operations on this storage account
func GetFileEndpoint(baseUri string, accountName string) string {
return fmt.Sprintf("https://%s.file.%s", accountName, baseUri)
}
// GetQueueEndpoint returns the endpoint for Queue API Operations on this storage account
func GetQueueEndpoint(baseUri string, accountName string) string {
return fmt.Sprintf("https://%s.queue.%s", accountName, baseUri)
}
// GetTableEndpoint returns the endpoint for Table API Operations on this storage account
func GetTableEndpoint(baseUri string, accountName string) string {
return fmt.Sprintf("https://%s.table.%s", accountName, baseUri)
}
giovanni-0.20.0/storage/internal/helpers/ 0000775 0000000 0000000 00000000000 14232154237 0020330 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/internal/helpers/errors.go 0000664 0000000 0000000 00000006516 14232154237 0022203 0 ustar 00root root 0000000 0000000 package helpers
import (
"encoding/json"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)
// TODO: trial switching over to this, then upstream it
// WithErrorUnlessStatusCode returns a RespondDecorator that emits an
// azure.RequestError by reading the response body unless the response HTTP status code
// is among the set passed.
//
// If there is a chance service may return responses other than the Azure error
// format and the response cannot be parsed into an error, a decoding error will
// be returned containing the response body. In any case, the Responder will
// return an error if the status code is not satisfied.
//
// If this Responder returns an error, the response body will be replaced with
// an in-memory reader, which needs no further closing.
func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator {
return func(r autorest.Responder) autorest.Responder {
return autorest.ResponderFunc(func(resp *http.Response) error {
err := r.Respond(resp)
if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) {
var e azure.RequestError
defer resp.Body.Close()
contentType := autorest.EncodedAsJSON
if resp != nil {
contentTypeStr := resp.Header.Get("Content-Type")
if strings.EqualFold(contentTypeStr, "application/xml") {
contentType = autorest.EncodedAsXML
}
}
// Copy and replace the Body in case it does not contain an error object.
// This will leave the Body available to the caller.
b, decodeErr := autorest.CopyAndDecode(contentType, resp.Body, &e)
resp.Body = ioutil.NopCloser(&b)
if decodeErr != nil {
return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr)
}
if e.ServiceError == nil {
switch contentType {
case autorest.EncodedAsJSON:
// Check if error is unwrapped ServiceError
if err := json.Unmarshal(b.Bytes(), &e.ServiceError); err != nil {
return err
}
break
case autorest.EncodedAsXML:
// Check if error is unwrapped ServiceError
if err := xml.Unmarshal(b.Bytes(), &e.ServiceError); err != nil {
return err
}
break
}
}
if e.ServiceError.Message == "" {
rawBody := map[string]interface{}{}
switch contentType {
case autorest.EncodedAsJSON:
// if we're here it means the returned error wasn't OData v4 compliant.
// try to unmarshal the body as raw JSON in hopes of getting something.
if err := json.Unmarshal(b.Bytes(), &rawBody); err != nil {
return err
}
break
case autorest.EncodedAsXML:
// if we're here it means the returned error wasn't OData v4 compliant.
// try to unmarshal the body as raw XML in hopes of getting something.
if err := xml.Unmarshal(b.Bytes(), &rawBody); err != nil {
return err
}
break
}
e.ServiceError = &azure.ServiceError{
Code: "Unknown",
Message: "Unknown service error",
}
if len(rawBody) > 0 {
e.ServiceError.Details = []map[string]interface{}{rawBody}
}
}
e.Response = resp
e.RequestID = azure.ExtractRequestID(resp)
if e.StatusCode == nil {
e.StatusCode = resp.StatusCode
}
err = &e
}
return err
})
}
}
giovanni-0.20.0/storage/internal/metadata/ 0000775 0000000 0000000 00000000000 14232154237 0020446 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/internal/metadata/parse.go 0000664 0000000 0000000 00000000665 14232154237 0022116 0 ustar 00root root 0000000 0000000 package metadata
import (
"net/http"
"strings"
)
// ParseFromHeaders parses the meta data from the headers
func ParseFromHeaders(headers http.Header) map[string]string {
metaData := make(map[string]string, 0)
for k, v := range headers {
key := strings.ToLower(k)
prefix := "x-ms-meta-"
if !strings.HasPrefix(key, prefix) {
continue
}
key = strings.TrimPrefix(key, prefix)
metaData[key] = v[0]
}
return metaData
}
giovanni-0.20.0/storage/internal/metadata/set.go 0000664 0000000 0000000 00000000466 14232154237 0021576 0 ustar 00root root 0000000 0000000 package metadata
import "fmt"
// SetIntoHeaders sets the provided MetaData into the headers
func SetIntoHeaders(headers map[string]interface{}, metaData map[string]string) map[string]interface{} {
for k, v := range metaData {
key := fmt.Sprintf("x-ms-meta-%s", k)
headers[key] = v
}
return headers
}
giovanni-0.20.0/storage/internal/metadata/validation.go 0000664 0000000 0000000 00000004011 14232154237 0023123 0 ustar 00root root 0000000 0000000 package metadata
import (
"fmt"
"regexp"
"strings"
)
var cSharpKeywords = map[string]*struct{}{
"abstract": {},
"as": {},
"base": {},
"bool": {},
"break": {},
"byte": {},
"case": {},
"catch": {},
"char": {},
"checked": {},
"class": {},
"const": {},
"continue": {},
"decimal": {},
"default": {},
"delegate": {},
"do": {},
"double": {},
"else": {},
"enum": {},
"event": {},
"explicit": {},
"extern": {},
"false": {},
"finally": {},
"fixed": {},
"float": {},
"for": {},
"foreach": {},
"goto": {},
"if": {},
"implicit": {},
"in": {},
"int": {},
"interface": {},
"internal": {},
"is": {},
"lock": {},
"long": {},
"namespace": {},
"new": {},
"null": {},
"object": {},
"operator": {},
"out": {},
"override": {},
"params": {},
"private": {},
"protected": {},
"public": {},
"readonly": {},
"ref": {},
"return": {},
"sbyte": {},
"sealed": {},
"short": {},
"sizeof": {},
"stackalloc": {},
"static": {},
"string": {},
"struct": {},
"switch": {},
"this": {},
"throw": {},
"true": {},
"try": {},
"typeof": {},
"uint": {},
"ulong": {},
"unchecked": {},
"unsafe": {},
"ushort": {},
"using": {},
"void": {},
"volatile": {},
"while": {},
}
func Validate(input map[string]string) error {
for k := range input {
isCSharpKeyword := cSharpKeywords[strings.ToLower(k)] != nil
if isCSharpKeyword {
return fmt.Errorf("%q is not a valid key (C# keyword)", k)
}
// must begin with a letter, underscore
// the rest: letters, digits and underscores
r, _ := regexp.Compile(`^([A-Za-z_]{1}[A-Za-z0-9_]{1,})$`)
if !r.MatchString(k) {
return fmt.Errorf("MetaData must start with letters or an underscores. Got %q.", k)
}
}
return nil
}
giovanni-0.20.0/storage/internal/metadata/validation_test.go 0000664 0000000 0000000 00000002244 14232154237 0024170 0 ustar 00root root 0000000 0000000 package metadata
import "testing"
func TestValidationCSharpKeywords(t *testing.T) {
for key := range cSharpKeywords {
t.Logf("[DEBUG] Testing %q", key)
err := Validate(map[string]string{
key: "value",
})
if err == nil {
t.Fatalf("Expected an error but didn't get one for %q", key)
}
}
}
func TestValidation(t *testing.T) {
testData := []struct {
Input string
ShouldBeValid bool
}{
{
Input: "",
ShouldBeValid: false,
},
{
Input: "abc123",
ShouldBeValid: true,
},
{
Input: "_abc123",
ShouldBeValid: true,
},
{
Input: "123abc",
ShouldBeValid: false,
},
{
Input: "a_123abc",
ShouldBeValid: true,
},
{
Input: "abc_123",
ShouldBeValid: true,
},
{
Input: "abc123_",
ShouldBeValid: true,
},
{
Input: "ABC123",
ShouldBeValid: true,
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)
err := Validate(map[string]string{
v.Input: "value",
})
actual := err == nil
if v.ShouldBeValid != actual {
t.Fatalf("Expected %t but got %t for %q", v.ShouldBeValid, actual, v.Input)
}
}
}
giovanni-0.20.0/storage/testdata/ 0000775 0000000 0000000 00000000000 14232154237 0016663 5 ustar 00root root 0000000 0000000 giovanni-0.20.0/storage/testdata/blank-large-file.dmg 0000664 0000000 0000000 00046164000 14232154237 0022463 0 ustar 00root root 0000000 0000000 sL UEFI PART \ Z8 sL " RL 1m}Ls) SFH 0eCF^
N`IL( OL d i s k i m a g e H+ ! HFSJ (%( ( 1 4k) 0 0 0 0 \ 0 xLNJxV4 @ @ .
B z`
z
h, ʸZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
&