From 14cb726fee938d7fe6e7074937b74c5447ec4f0c Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 12 Jul 2019 11:48:12 +0100 Subject: [PATCH 1/6] r/virtual_machine: retrieving the OS/Data Disks from Azure, rather than trying to parse the config This ensures that all Disks attached to the Virtual Machine should be deleted at deletion time should the user be opted into it. This also exposes the full (correctly cased/validated ID's) such that we can switch to using the new storage sdk --- azurerm/resource_arm_virtual_machine.go | 109 ++++++++++++++++-------- 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/azurerm/resource_arm_virtual_machine.go b/azurerm/resource_arm_virtual_machine.go index c33b5a8c3429..1e6ce1664b9f 100644 --- a/azurerm/resource_arm_virtual_machine.go +++ b/azurerm/resource_arm_virtual_machine.go @@ -27,6 +27,7 @@ func resourceArmVirtualMachine() *schema.Resource { Read: resourceArmVirtualMachineRead, Update: resourceArmVirtualMachineCreateUpdate, Delete: resourceArmVirtualMachineDelete, + // TODO: use a custom importer so that `delete_os_disk_on_termination` and `delete_data_disks_on_termination` are set Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -848,61 +849,78 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e azureRMLockByName(name, virtualMachineResourceName) defer azureRMUnlockByName(name, virtualMachineResourceName) + virtualMachine, err := client.Get(ctx, resGroup, name, compute.InstanceView) + if err != nil { + return fmt.Errorf("Error retrieving Virtual Machine %q (Resource Group %q): %s", name, resGroup, err) + } + future, err := client.Delete(ctx, resGroup, name) if err != nil { - return err + return fmt.Errorf("Error deleting Virtual Machine %q (Resource Group %q): %s", name, resGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return err + return fmt.Errorf("Error waiting for deletion of Virtual Machine %q (Resource Group %q): %s", name, resGroup, err) } // delete OS Disk if opted in - if deleteOsDisk := d.Get("delete_os_disk_on_termination").(bool); deleteOsDisk { - log.Printf("[INFO] delete_os_disk_on_termination is enabled, deleting disk from %s", name) + deleteOsDisk := d.Get("delete_os_disk_on_termination").(bool) + deleteDataDisks := d.Get("delete_data_disks_on_termination").(bool) - osDisk, err := expandAzureRmVirtualMachineOsDisk(d) - if err != nil { - return fmt.Errorf("Error expanding OS Disk: %s", err) + if deleteOsDisk || deleteDataDisks { + props := virtualMachine.VirtualMachineProperties + if props == nil { + return fmt.Errorf("Error deleting OS Disk for Virtual Machine %q - `props` was nil", name) + } + storageProfile := props.StorageProfile + if storageProfile != nil { + return fmt.Errorf("Error deleting OS Disk for Virtual Machine %q - `storageProfile` was nil", name) } - if osDisk.Vhd != nil { - if osDisk.Vhd.URI != nil { - if err = resourceArmVirtualMachineDeleteVhd(*osDisk.Vhd.URI, meta); err != nil { + if deleteOsDisk { + log.Printf("[INFO] delete_os_disk_on_termination is enabled, deleting disk from %s", name) + osDisk := storageProfile.OsDisk + if osDisk == nil { + return fmt.Errorf("Error deleting OS Disk for Virtual Machine %q - `osDisk` was nil", name) + } + if osDisk.Vhd == nil && osDisk.ManagedDisk == nil { + return fmt.Errorf("Unable to determine OS Disk Type to Delete it for Virtual Machine %q", name) + } + + if osDisk.Vhd != nil { + if err = resourceArmVirtualMachineDeleteVhd(osDisk.Vhd, meta); err != nil { return fmt.Errorf("Error deleting OS Disk VHD: %+v", err) } - } - } else if osDisk.ManagedDisk != nil { - if osDisk.ManagedDisk.ID != nil { - if err = resourceArmVirtualMachineDeleteManagedDisk(*osDisk.ManagedDisk.ID, meta); err != nil { + } else if osDisk.ManagedDisk != nil { + if err = resourceArmVirtualMachineDeleteManagedDisk(osDisk.ManagedDisk, meta); err != nil { return fmt.Errorf("Error deleting OS Managed Disk: %+v", err) } } - } else { - return fmt.Errorf("Unable to locate OS managed disk properties from %s", name) } - } - // delete Data disks if opted in - if deleteDataDisks := d.Get("delete_data_disks_on_termination").(bool); deleteDataDisks { - log.Printf("[INFO] delete_data_disks_on_termination is enabled, deleting each data disk from %s", name) + // delete Data disks if opted in + if deleteDataDisks { + log.Printf("[INFO] delete_data_disks_on_termination is enabled, deleting each data disk from %q", name) - disks, err := expandAzureRmVirtualMachineDataDisk(d) - if err != nil { - return fmt.Errorf("Error expanding Data Disks: %s", err) - } + dataDisks := storageProfile.DataDisks + if dataDisks == nil { + return fmt.Errorf("Error deleting Data Disks for Virtual Machine %q: `dataDisks` was nil", name) + } - for _, disk := range disks { - if disk.Vhd != nil { - if err = resourceArmVirtualMachineDeleteVhd(*disk.Vhd.URI, meta); err != nil { - return fmt.Errorf("Error deleting Data Disk VHD: %+v", err) + for _, disk := range *dataDisks { + if disk.Vhd == nil && disk.ManagedDisk == nil { + return fmt.Errorf("Unable to determine Data Disk Type to Delete it for Virtual Machine %q / Disk %q", name, *disk.Name) } - } else if disk.ManagedDisk != nil { - if err = resourceArmVirtualMachineDeleteManagedDisk(*disk.ManagedDisk.ID, meta); err != nil { - return fmt.Errorf("Error deleting Data Managed Disk: %+v", err) + + if disk.Vhd != nil { + if err = resourceArmVirtualMachineDeleteVhd(disk.Vhd, meta); err != nil { + return fmt.Errorf("Error deleting Data Disk VHD: %+v", err) + } + } else if disk.ManagedDisk != nil { + if err = resourceArmVirtualMachineDeleteManagedDisk(disk.ManagedDisk, meta); err != nil { + return fmt.Errorf("Error deleting Data Managed Disk: %+v", err) + } } - } else { - return fmt.Errorf("Unable to locate data managed disk properties from %s", name) } } } @@ -910,7 +928,16 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e return nil } -func resourceArmVirtualMachineDeleteVhd(uri string, meta interface{}) error { +func resourceArmVirtualMachineDeleteVhd(vhd *compute.VirtualHardDisk, meta interface{}) error { + if vhd == nil { + return fmt.Errorf("`vhd` was nil`") + } + if vhd.URI == nil { + return fmt.Errorf("`vhd.URI` was nil`") + } + + uri := *vhd.URI + armClient := meta.(*ArmClient) ctx := armClient.StopContext environment := armClient.environment @@ -958,7 +985,15 @@ func resourceArmVirtualMachineDeleteVhd(uri string, meta interface{}) error { return nil } -func resourceArmVirtualMachineDeleteManagedDisk(managedDiskID string, meta interface{}) error { +func resourceArmVirtualMachineDeleteManagedDisk(disk *compute.ManagedDiskParameters, meta interface{}) error { + if disk == nil { + return fmt.Errorf("`disk` was nil`") + } + if disk.ID == nil { + return fmt.Errorf("`disk.ID` was nil`") + } + managedDiskID := *disk.ID + client := meta.(*ArmClient).diskClient ctx := meta.(*ArmClient).StopContext @@ -971,11 +1006,11 @@ func resourceArmVirtualMachineDeleteManagedDisk(managedDiskID string, meta inter future, err := client.Delete(ctx, resGroup, name) if err != nil { - return fmt.Errorf("Error deleting Managed Disk (%s %s) %+v", name, resGroup, err) + return fmt.Errorf("Error deleting Managed Disk %q (Resource Group %q) %+v", name, resGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error deleting Managed Disk (%s %s) %+v", name, resGroup, err) + return fmt.Errorf("Error waiting for deletion of Managed Disk %q (Resource Group %q) %+v", name, resGroup, err) } return nil From d06390d0cafe7f13484c5e5d47113e75fd1bb269 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 12 Jul 2019 12:09:26 +0100 Subject: [PATCH 2/6] r/virtual_machine: deleting the os disk using the new sdk --- azurerm/internal/services/storage/client.go | 13 +++++ azurerm/resource_arm_virtual_machine.go | 58 +++++++-------------- 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/azurerm/internal/services/storage/client.go b/azurerm/internal/services/storage/client.go index a32d3ebca575..6520c77e467e 100644 --- a/azurerm/internal/services/storage/client.go +++ b/azurerm/internal/services/storage/client.go @@ -8,6 +8,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/authorizers" + "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/directories" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues" @@ -60,6 +61,18 @@ func (client Client) FindResourceGroup(ctx context.Context, accountName string) return resourceGroup, nil } +func (client Client) BlobsClient(ctx context.Context, resourceGroup, accountName string) (*blobs.Client, error) { + accountKey, err := client.findAccountKey(ctx, resourceGroup, accountName) + if err != nil { + return nil, fmt.Errorf("Error retrieving Account Key: %s", err) + } + + storageAuth := authorizers.NewSharedKeyLiteAuthorizer(accountName, *accountKey) + blobsClient := blobs.New() + blobsClient.Client.Authorizer = storageAuth + return &blobsClient, nil +} + func (client Client) FileShareDirectoriesClient(ctx context.Context, resourceGroup, accountName string) (*directories.Client, error) { accountKey, err := client.findAccountKey(ctx, resourceGroup, accountName) if err != nil { diff --git a/azurerm/resource_arm_virtual_machine.go b/azurerm/resource_arm_virtual_machine.go index 1e6ce1664b9f..3ab330fc63d3 100644 --- a/azurerm/resource_arm_virtual_machine.go +++ b/azurerm/resource_arm_virtual_machine.go @@ -4,18 +4,18 @@ import ( "bytes" "fmt" "log" - "net/url" "strings" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-06-01/compute" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-12-01/network" - "github.com/Azure/azure-sdk-for-go/storage" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + intStor "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs" "golang.org/x/net/context" ) @@ -868,6 +868,8 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e deleteDataDisks := d.Get("delete_data_disks_on_termination").(bool) if deleteOsDisk || deleteDataDisks { + storageClient := meta.(*ArmClient).storage + props := virtualMachine.VirtualMachineProperties if props == nil { return fmt.Errorf("Error deleting OS Disk for Virtual Machine %q - `props` was nil", name) @@ -888,7 +890,7 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e } if osDisk.Vhd != nil { - if err = resourceArmVirtualMachineDeleteVhd(osDisk.Vhd, meta); err != nil { + if err = resourceArmVirtualMachineDeleteVhd(ctx, storageClient, osDisk.Vhd); err != nil { return fmt.Errorf("Error deleting OS Disk VHD: %+v", err) } } else if osDisk.ManagedDisk != nil { @@ -913,7 +915,7 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e } if disk.Vhd != nil { - if err = resourceArmVirtualMachineDeleteVhd(disk.Vhd, meta); err != nil { + if err = resourceArmVirtualMachineDeleteVhd(ctx, storageClient, disk.Vhd); err != nil { return fmt.Errorf("Error deleting Data Disk VHD: %+v", err) } } else if disk.ManagedDisk != nil { @@ -928,7 +930,7 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e return nil } -func resourceArmVirtualMachineDeleteVhd(vhd *compute.VirtualHardDisk, meta interface{}) error { +func resourceArmVirtualMachineDeleteVhd(ctx context.Context, storageClient *intStor.Client, vhd *compute.VirtualHardDisk) error { if vhd == nil { return fmt.Errorf("`vhd` was nil`") } @@ -937,49 +939,29 @@ func resourceArmVirtualMachineDeleteVhd(vhd *compute.VirtualHardDisk, meta inter } uri := *vhd.URI - - armClient := meta.(*ArmClient) - ctx := armClient.StopContext - environment := armClient.environment - - vhdURL, err := url.Parse(uri) + id, err := blobs.ParseResourceID(uri) if err != nil { - return fmt.Errorf("Cannot parse Disk VHD URI: %s", err) - } - - blobDomainSuffix := environment.StorageEndpointSuffix - if !strings.HasSuffix(strings.ToLower(vhdURL.Host), strings.ToLower(blobDomainSuffix)) { - return fmt.Errorf("Error: Disk VHD URI %q doesn't appear to be a Blob Storage URI (%q) - expected a suffix of %q)", uri, vhdURL.Host, blobDomainSuffix) + return fmt.Errorf("Error parsing %q: %s", uri, err) } - // VHD URI is in the form: https://storageAccountName.blob.core.windows.net/containerName/blobName - storageAccountName := strings.Split(vhdURL.Host, ".")[0] - path := strings.Split(strings.TrimPrefix(vhdURL.Path, "/"), "/") - containerName := path[0] - blobName := path[1] - - resourceGroupName, err := findStorageAccountResourceGroup(meta, storageAccountName) + resourceGroup, err := storageClient.FindResourceGroup(ctx, id.AccountName) if err != nil { - return fmt.Errorf("Error finding resource group for storage account %s: %+v", storageAccountName, err) + return fmt.Errorf("Error locating Resource Group for Storage Account %q: %s", id.AccountName, err) + } + if resourceGroup == nil { + return fmt.Errorf("Unable to locate Resource Group for Storage Account %q (Disk %q)!", id.AccountName, uri) } - blobClient, saExists, err := armClient.getBlobStorageClientForStorageAccount(ctx, resourceGroupName, storageAccountName) + blobsClient, err := storageClient.BlobsClient(ctx, *resourceGroup, id.AccountName) if err != nil { - return fmt.Errorf("Error creating blob store client for VHD deletion: %+v", err) + return fmt.Errorf("Error building Blobs Client: %s", err) } - if !saExists { - log.Printf("[INFO] Storage Account %q in resource group %q doesn't exist so the VHD blob won't exist", storageAccountName, resourceGroupName) - return nil + input := blobs.DeleteInput{ + DeleteSnapshots: false, } - - log.Printf("[INFO] Deleting VHD blob %s", blobName) - container := blobClient.GetContainerReference(containerName) - blob := container.GetBlobReference(blobName) - options := &storage.DeleteBlobOptions{} - err = blob.Delete(options) - if err != nil { - return fmt.Errorf("Error deleting VHD blob: %+v", err) + if _, err := blobsClient.Delete(ctx, id.AccountName, id.ContainerName, id.BlobName, input); err != nil { + return fmt.Errorf("Error deleting Blob %q (Container %q / Account %q / Resource Group %q): %s", id.BlobName, id.ContainerName, id.AccountName, *resourceGroup, err) } return nil From 3b9e7021745c48ad7d812e5d3e45aa957c6bcaa8 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 12 Jul 2019 12:26:16 +0100 Subject: [PATCH 3/6] r/virtual_machine: switching to use the new Storage SDK for tests --- azurerm/resource_arm_virtual_machine.go | 6 +-- ...rm_virtual_machine_unmanaged_disks_test.go | 38 +++++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/azurerm/resource_arm_virtual_machine.go b/azurerm/resource_arm_virtual_machine.go index 3ab330fc63d3..0068d67d9cce 100644 --- a/azurerm/resource_arm_virtual_machine.go +++ b/azurerm/resource_arm_virtual_machine.go @@ -849,7 +849,7 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e azureRMLockByName(name, virtualMachineResourceName) defer azureRMUnlockByName(name, virtualMachineResourceName) - virtualMachine, err := client.Get(ctx, resGroup, name, compute.InstanceView) + virtualMachine, err := client.Get(ctx, resGroup, name, "") if err != nil { return fmt.Errorf("Error retrieving Virtual Machine %q (Resource Group %q): %s", name, resGroup, err) } @@ -872,11 +872,11 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e props := virtualMachine.VirtualMachineProperties if props == nil { - return fmt.Errorf("Error deleting OS Disk for Virtual Machine %q - `props` was nil", name) + return fmt.Errorf("Error deleting Disks for Virtual Machine %q - `props` was nil", name) } storageProfile := props.StorageProfile if storageProfile != nil { - return fmt.Errorf("Error deleting OS Disk for Virtual Machine %q - `storageProfile` was nil", name) + return fmt.Errorf("Error deleting Disks for Virtual Machine %q - `storageProfile` was nil", name) } if deleteOsDisk { diff --git a/azurerm/resource_arm_virtual_machine_unmanaged_disks_test.go b/azurerm/resource_arm_virtual_machine_unmanaged_disks_test.go index 6e7eb685f484..2515de5d1132 100644 --- a/azurerm/resource_arm_virtual_machine_unmanaged_disks_test.go +++ b/azurerm/resource_arm_virtual_machine_unmanaged_disks_test.go @@ -12,6 +12,8 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs" ) func TestAccAzureRMVirtualMachine_basicLinuxMachine(t *testing.T) { @@ -3010,35 +3012,41 @@ resource "azurerm_virtual_machine" "test" { `, rInt, location, rInt, rInt, rInt, rInt, rInt) } -func testCheckAzureRMVirtualMachineVHDExistence(name string, shouldExist bool) resource.TestCheckFunc { +func testCheckAzureRMVirtualMachineVHDExistence(blobName string, shouldExist bool) resource.TestCheckFunc { return func(s *terraform.State) error { for _, rs := range s.RootModule().Resources { if rs.Type != "azurerm_storage_container" { continue } - // fetch storage account and container name resourceGroup := rs.Primary.Attributes["resource_group_name"] - storageAccountName := rs.Primary.Attributes["storage_account_name"] + accountName := rs.Primary.Attributes["storage_account_name"] containerName := rs.Primary.Attributes["name"] - armClient := testAccProvider.Meta().(*ArmClient) - ctx := armClient.StopContext - storageClient, _, err := armClient.getBlobStorageClientForStorageAccount(ctx, resourceGroup, storageAccountName) + + storageClient := testAccProvider.Meta().(*ArmClient).storage + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + client, err := storageClient.BlobsClient(ctx, resourceGroup, accountName) if err != nil { - return fmt.Errorf("Error creating Blob storage client: %+v", err) + return fmt.Errorf("Error building Blobs Client: %s", err) } - container := storageClient.GetContainerReference(containerName) - blob := container.GetBlobReference(name) - exists, err := blob.Exists() + input := blobs.GetPropertiesInput{} + props, err := client.GetProperties(ctx, accountName, containerName, blobName, input) if err != nil { - return fmt.Errorf("Error checking if Disk VHD Blob exists: %+v", err) + if utils.ResponseWasNotFound(props.Response) { + if !shouldExist { + return nil + } + + return fmt.Errorf("The Blob for the Unmanaged Disk %q should exist in the Container %q but it didn't!", blobName, containerName) + } + + return fmt.Errorf("Error retrieving properties for Blob %q (Container %q): %s", blobName, containerName, err) } - if exists && !shouldExist { - return fmt.Errorf("Disk VHD Blob still exists %s %s", containerName, name) - } else if !exists && shouldExist { - return fmt.Errorf("Disk VHD Blob should exist %s %s", containerName, name) + if !shouldExist { + return fmt.Errorf("The Blob for the Unmanaged Disk %q shouldn't exist in the Container %q but it did!", blobName, containerName) } } From f9b81fc0286dae98906a54c75de7d4568b92b913 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 12 Jul 2019 12:27:51 +0100 Subject: [PATCH 4/6] Vendoring the Blobs SDK from github.com/tombuildsstuff/giovanni --- .../storage/2018-11-09/blob/blobs/README.md | 46 +++ .../2018-11-09/blob/blobs/append_block.go | 170 ++++++++++ .../storage/2018-11-09/blob/blobs/client.go | 25 ++ .../storage/2018-11-09/blob/blobs/copy.go | 235 +++++++++++++ .../2018-11-09/blob/blobs/copy_abort.go | 110 +++++++ .../2018-11-09/blob/blobs/copy_and_wait.go | 41 +++ .../storage/2018-11-09/blob/blobs/delete.go | 105 ++++++ .../2018-11-09/blob/blobs/delete_snapshot.go | 108 ++++++ .../2018-11-09/blob/blobs/delete_snapshots.go | 99 ++++++ .../storage/2018-11-09/blob/blobs/get.go | 116 +++++++ .../2018-11-09/blob/blobs/get_block_list.go | 140 ++++++++ .../2018-11-09/blob/blobs/get_page_ranges.go | 152 +++++++++ .../blob/blobs/incremental_copy_blob.go | 120 +++++++ .../2018-11-09/blob/blobs/lease_acquire.go | 135 ++++++++ .../2018-11-09/blob/blobs/lease_break.go | 124 +++++++ .../2018-11-09/blob/blobs/lease_change.go | 117 +++++++ .../2018-11-09/blob/blobs/lease_release.go | 98 ++++++ .../2018-11-09/blob/blobs/lease_renew.go | 97 ++++++ .../2018-11-09/blob/blobs/metadata_set.go | 113 +++++++ .../storage/2018-11-09/blob/blobs/models.go | 82 +++++ .../2018-11-09/blob/blobs/properties_get.go | 310 ++++++++++++++++++ .../2018-11-09/blob/blobs/properties_set.go | 156 +++++++++ .../2018-11-09/blob/blobs/put_append_blob.go | 134 ++++++++ .../2018-11-09/blob/blobs/put_block.go | 125 +++++++ .../2018-11-09/blob/blobs/put_block_blob.go | 135 ++++++++ .../blob/blobs/put_block_blob_file.go | 34 ++ .../2018-11-09/blob/blobs/put_block_list.go | 157 +++++++++ .../2018-11-09/blob/blobs/put_block_url.go | 129 ++++++++ .../2018-11-09/blob/blobs/put_page_blob.go | 148 +++++++++ .../2018-11-09/blob/blobs/put_page_clear.go | 113 +++++++ .../2018-11-09/blob/blobs/put_page_update.go | 163 +++++++++ .../2018-11-09/blob/blobs/resource_id.go | 56 ++++ .../storage/2018-11-09/blob/blobs/set_tier.go | 93 ++++++ .../storage/2018-11-09/blob/blobs/snapshot.go | 163 +++++++++ .../blob/blobs/snapshot_get_properties.go | 90 +++++ .../storage/2018-11-09/blob/blobs/undelete.go | 92 ++++++ .../storage/2018-11-09/blob/blobs/version.go | 14 + vendor/modules.txt | 1 + 38 files changed, 4346 insertions(+) create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/README.md create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/append_block.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/client.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_abort.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_and_wait.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshot.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshots.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_block_list.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_page_ranges.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/incremental_copy_blob.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_acquire.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_break.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_change.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_release.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_renew.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/metadata_set.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/models.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_get.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_set.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_append_blob.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob_file.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_list.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_url.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_blob.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_clear.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_update.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/resource_id.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/set_tier.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot_get_properties.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/undelete.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/version.go diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/README.md b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/README.md new file mode 100644 index 000000000000..c2469935adcd --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/README.md @@ -0,0 +1,46 @@ +## 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/18.04.2/ubuntu-18.04.2-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 +} + +``` \ No newline at end of file diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/append_block.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/append_block.go new file mode 100644 index 000000000000..7fed86a319b0 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/append_block.go @@ -0,0 +1,170 @@ +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. + 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 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 + } + + 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)) +} + +// 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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/client.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/client.go new file mode 100644 index 000000000000..db20391922bb --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/client.go @@ -0,0 +1,25 @@ +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, + } +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy.go new file mode 100644 index 000000000000..febaab5f9a91 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy.go @@ -0,0 +1,235 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_abort.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_abort.go new file mode 100644 index 000000000000..a992ff199bb1 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_abort.go @@ -0,0 +1,110 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_and_wait.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_and_wait.go new file mode 100644 index 000000000000..a1e7fa453dc0 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/copy_and_wait.go @@ -0,0 +1,41 @@ +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") +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete.go new file mode 100644 index 000000000000..c1c642d7d781 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete.go @@ -0,0 +1,105 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshot.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshot.go new file mode 100644 index 000000000000..18c3d4cffe3f --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshot.go @@ -0,0 +1,108 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshots.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshots.go new file mode 100644 index 000000000000..e7e2b664d74d --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/delete_snapshots.go @@ -0,0 +1,99 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get.go new file mode 100644 index 000000000000..fa8808197cfb --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get.go @@ -0,0 +1,116 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_block_list.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_block_list.go new file mode 100644 index 000000000000..9f8120c6c8c3 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_block_list.go @@ -0,0 +1,140 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_page_ranges.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_page_ranges.go new file mode 100644 index 000000000000..37abf631a28a --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/get_page_ranges.go @@ -0,0 +1,152 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/incremental_copy_blob.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/incremental_copy_blob.go new file mode 100644 index 000000000000..7fb7e6b55489 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/incremental_copy_blob.go @@ -0,0 +1,120 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_acquire.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_acquire.go new file mode 100644 index 000000000000..432c1f5fcda9 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_acquire.go @@ -0,0 +1,135 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_break.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_break.go new file mode 100644 index 000000000000..d5642045d20d --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_break.go @@ -0,0 +1,124 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_change.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_change.go new file mode 100644 index 000000000000..c57f9db875b0 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_change.go @@ -0,0 +1,117 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_release.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_release.go new file mode 100644 index 000000000000..0226cdf37552 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_release.go @@ -0,0 +1,98 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_renew.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_renew.go new file mode 100644 index 000000000000..69c495bd9898 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/lease_renew.go @@ -0,0 +1,97 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/metadata_set.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/metadata_set.go new file mode 100644 index 000000000000..ec69152a5f98 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/metadata_set.go @@ -0,0 +1,113 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/models.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/models.go new file mode 100644 index 000000000000..d7d83aade8c0 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/models.go @@ -0,0 +1,82 @@ +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"` +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_get.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_get.go new file mode 100644 index 000000000000..de7c5fced3b5 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_get.go @@ -0,0 +1,310 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_set.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_set.go new file mode 100644 index 000000000000..a8c0ed8cba95 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/properties_set.go @@ -0,0 +1,156 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_append_blob.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_append_blob.go new file mode 100644 index 000000000000..ef2c5025d606 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_append_blob.go @@ -0,0 +1,134 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block.go new file mode 100644 index 000000000000..5256013a1a09 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block.go @@ -0,0 +1,125 @@ +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, + } + + 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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob.go new file mode 100644 index 000000000000..fa29dd38011e --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob.go @@ -0,0 +1,135 @@ +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 len(input.Content) == 0 { + return result, validation.NewError("blobs.Client", "PutBlockBlob", "`input.Content` cannot be 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 + } + + 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.WithBytes(&input.Content)) + 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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob_file.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob_file.go new file mode 100644 index 000000000000..7232e5e4e456 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_blob_file.go @@ -0,0 +1,34 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_list.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_list.go new file mode 100644 index 000000000000..f80524790be5 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_list.go @@ -0,0 +1,157 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_url.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_url.go new file mode 100644 index 000000000000..95ad974698bd --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_block_url.go @@ -0,0 +1,129 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_blob.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_blob.go new file mode 100644 index 000000000000..ad3c8788c862 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_blob.go @@ -0,0 +1,148 @@ +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", "`blobName` 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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_clear.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_clear.go new file mode 100644 index 000000000000..59feaa5d93d0 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_clear.go @@ -0,0 +1,113 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_update.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_update.go new file mode 100644 index 000000000000..a47e8cac649c --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/put_page_update.go @@ -0,0 +1,163 @@ +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), + } + + 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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/resource_id.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/resource_id.go new file mode 100644 index 000000000000..4057cf275676 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/resource_id.go @@ -0,0 +1,56 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/set_tier.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/set_tier.go new file mode 100644 index 000000000000..dd0f0b8782b1 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/set_tier.go @@ -0,0 +1,93 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot.go new file mode 100644 index 000000000000..180070b29469 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot.go @@ -0,0 +1,163 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot_get_properties.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot_get_properties.go new file mode 100644 index 000000000000..fe1be63ab216 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/snapshot_get_properties.go @@ -0,0 +1,90 @@ +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)) +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/undelete.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/undelete.go new file mode 100644 index 000000000000..9be2f81a66f2 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/undelete.go @@ -0,0 +1,92 @@ +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 +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/version.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/version.go new file mode 100644 index 000000000000..ad61a5700a50 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs/version.go @@ -0,0 +1,14 @@ +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) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index bdc280bd98d7..b7365f6571f2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -339,6 +339,7 @@ github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/tf github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate github.com/terraform-providers/terraform-provider-azuread/version # github.com/tombuildsstuff/giovanni v0.2.1 +github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/directories github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues From d367f7ff3c93d0f8d0e2bbddbd2a1e9e86848512 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 12 Jul 2019 16:08:13 +0100 Subject: [PATCH 5/6] fixing the check --- azurerm/resource_arm_virtual_machine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_virtual_machine.go b/azurerm/resource_arm_virtual_machine.go index 0068d67d9cce..eff093bc0f4b 100644 --- a/azurerm/resource_arm_virtual_machine.go +++ b/azurerm/resource_arm_virtual_machine.go @@ -875,7 +875,7 @@ func resourceArmVirtualMachineDelete(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error deleting Disks for Virtual Machine %q - `props` was nil", name) } storageProfile := props.StorageProfile - if storageProfile != nil { + if storageProfile == nil { return fmt.Errorf("Error deleting Disks for Virtual Machine %q - `storageProfile` was nil", name) } From 163d682574bea13da63c61436fb29655be8cfc8d Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 12 Jul 2019 16:48:32 +0100 Subject: [PATCH 6/6] r/virtual_machine: removing the unused `findStorageAccountResourceGroup` func --- azurerm/resource_arm_virtual_machine.go | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/azurerm/resource_arm_virtual_machine.go b/azurerm/resource_arm_virtual_machine.go index eff093bc0f4b..0db2cee0b388 100644 --- a/azurerm/resource_arm_virtual_machine.go +++ b/azurerm/resource_arm_virtual_machine.go @@ -1764,31 +1764,6 @@ func expandAzureRmVirtualMachineOsDisk(d *schema.ResourceData) (*compute.OSDisk, return osDisk, nil } -func findStorageAccountResourceGroup(meta interface{}, storageAccountName string) (string, error) { - client := meta.(*ArmClient).resourcesClient - ctx := meta.(*ArmClient).StopContext - filter := fmt.Sprintf("name eq '%s' and resourceType eq 'Microsoft.Storage/storageAccounts'", storageAccountName) - expand := "" - var pager *int32 - - rf, err := client.List(ctx, filter, expand, pager) - if err != nil { - return "", fmt.Errorf("Error making resource request for query %s: %+v", filter, err) - } - - results := rf.Values() - if len(results) != 1 { - return "", fmt.Errorf("Wrong number of results making resource request for query %s: %d", filter, len(results)) - } - - id, err := parseAzureResourceID(*results[0].ID) - if err != nil { - return "", err - } - - return id.ResourceGroup, nil -} - func resourceArmVirtualMachineStorageOsProfileHash(v interface{}) int { var buf bytes.Buffer