package azure import ( "bytes" "context" "crypto/md5" "fmt" "io" "net/url" "os" "os/exec" "path" "testing" "github.com/Azure/azure-storage-blob-go/azblob" ) func handleErrors(t *testing.T, err error) { if err != nil { t.Fatal(err) } } func loadEnvVar(t *testing.T, envVarName string) (string, bool) { variable, exists := os.LookupEnv(envVarName) if !exists { t.Logf("Environment variable does not exist: %s", envVarName) return "", false } return variable, true } func TestAzure_FileUpload(t *testing.T) { // Load configuration storageAccount, saExists := loadEnvVar(t, "AZURE_STORAGE_ACCOUNT") storageAccessKey, sakExists := loadEnvVar(t, "AZURE_STORAGE_ACCESS_KEY") containerName, cnExists := loadEnvVar(t, "AZURE_STORAGE_CONTAINER") fileName := "/tmp/testing-image.vhd" var threads int = 4 // Workaround Travis security feature. If non of the variables is set, just ignore the test if saExists == false && sakExists == false && cnExists == false { t.Log("No AZURE configuration provided, assuming that this is running in CI. Skipping the test.") return } // If only one/two of them are not set, then fail if saExists == false || sakExists == false || cnExists == false { t.Fatal("You need to define all variables for AZURE connection.") } // Prepare the file cmd := exec.Command("dd", "bs=512", "count=512", "if=/dev/urandom", fmt.Sprintf("of=%s", fileName)) err := cmd.Run() handleErrors(t, err) t.Log("Image to upload is:", fileName) // Calculate MD5 sum of the file f, err := os.Open(fileName) handleErrors(t, err) h := md5.New() _, err = io.Copy(h, f) handleErrors(t, err) imageChecksum := h.Sum(nil) err = f.Close() handleErrors(t, err) credentials := Credentials{ StorageAccount: storageAccount, StorageAccessKey: storageAccessKey, } metadata := ImageMetadata{ ImageName: path.Base(fileName), ContainerName: containerName, } // Upload the image err = UploadImage(credentials, metadata, fileName, threads) handleErrors(t, err) // Download the image // Create a default request pipeline using your storage account name and account key. credential, err := azblob.NewSharedKeyCredential(credentials.StorageAccount, credentials.StorageAccessKey) handleErrors(t, err) p := azblob.NewPipeline(credential, azblob.PipelineOptions{}) // get storage account blob service URL endpoint. URL, _ := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s", credentials.StorageAccount, metadata.ContainerName)) // Create a ContainerURL object that wraps the container URL and a request // pipeline to make requests. containerURL := azblob.NewContainerURL(*URL, p) // Create the container, use a never-expiring context ctx := context.Background() blobURL := containerURL.NewPageBlobURL(metadata.ImageName) get, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false) handleErrors(t, err) blobData := &bytes.Buffer{} reader := get.Body(azblob.RetryReaderOptions{}) _, err = blobData.ReadFrom(reader) handleErrors(t, err) reader.Close() // The client must close the response body when finished with it blobBytes := blobData.Bytes() blobChecksum := md5.Sum(blobBytes) t.Logf("Local image checksum: %x\n", imageChecksum) t.Logf("Downloaded blob checksum : %x\n", blobChecksum) // Delete the blob and throw away any errors _, _ = blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionInclude, azblob.BlobAccessConditions{}) _ = os.Remove(fileName) if !bytes.Equal(imageChecksum, blobChecksum[:]) { t.Fatalf("Checksums do not match! Local file: %x, cloud blob: %x", imageChecksum, blobChecksum[:]) } }