Provide default values for UploadStreamToBlockBlobOptions and refactor UploadStreamToBlockBlob (#167)

* Refactor of UploadStreamToBlockBlobOptions

Refactor to remove bugs and extra complexity.

* Migrate stream code to own file. Add concurrency.

After benchmarking, code was 25% slower without concurrency in azcopy, regardless of buffer sizing.

This change introduces back concurrency, but with a much simpler model and still eliminating the the atomic operations.

* Update to use io.ReadFull()

Adding test.

Benchmarks are now on par with the original code.  Here is 10 runs using the current azcopy binary and a binary built from changed code:

Binary = bins/azcopy_original(run 1)
	Benchmark 1KiB file: 338.314573ms
	Benchmark 1MiB file: 484.967288ms
	Benchmark 10MiB file: 760.810541ms
	Benchmark 100MiB file: 1.351661794s
	Benchmark 1GiB file: 10.826069714s
Binary = bins/azcopy_original(run 2)
	Benchmark 1KiB file: 207.941537ms
	Benchmark 1MiB file: 460.838416ms
	Benchmark 10MiB file: 760.783836ms
	Benchmark 100MiB file: 1.501405998s
	Benchmark 1GiB file: 7.18717018s
Binary = bins/azcopy_original(run 3)
	Benchmark 1KiB file: 212.47363ms
	Benchmark 1MiB file: 467.623706ms
	Benchmark 10MiB file: 698.447313ms
	Benchmark 100MiB file: 1.292167757s
	Benchmark 1GiB file: 7.637774779s
Binary = bins/azcopy_original(run 4)
	Benchmark 1KiB file: 276.746547ms
	Benchmark 1MiB file: 465.676606ms
	Benchmark 10MiB file: 646.126277ms
	Benchmark 100MiB file: 1.087617614s
	Benchmark 1GiB file: 6.546629743s
Binary = bins/azcopy_original(run 5)
	Benchmark 1KiB file: 224.753013ms
	Benchmark 1MiB file: 468.194201ms
	Benchmark 10MiB file: 658.754858ms
	Benchmark 100MiB file: 1.287728254s
	Benchmark 1GiB file: 7.349753091s
Binary = bins/azcopy_original(run 6)
	Benchmark 1KiB file: 215.433224ms
	Benchmark 1MiB file: 468.2654ms
	Benchmark 10MiB file: 736.859155ms
	Benchmark 100MiB file: 1.288282248s
	Benchmark 1GiB file: 9.901807484s
Binary = bins/azcopy_original(run 7)
	Benchmark 1KiB file: 309.374802ms
	Benchmark 1MiB file: 466.3705ms
	Benchmark 10MiB file: 764.919816ms
	Benchmark 100MiB file: 1.288119942s
	Benchmark 1GiB file: 12.568692895s
Binary = bins/azcopy_original(run 8)
	Benchmark 1KiB file: 223.696311ms
	Benchmark 1MiB file: 459.585207ms
	Benchmark 10MiB file: 861.388787ms
	Benchmark 100MiB file: 2.001739213s
	Benchmark 1GiB file: 14.062394287s
Binary = bins/azcopy_original(run 9)
	Benchmark 1KiB file: 213.478124ms
	Benchmark 1MiB file: 472.516087ms
	Benchmark 10MiB file: 888.345447ms
	Benchmark 100MiB file: 1.712670977s
	Benchmark 1GiB file: 7.351456844s
Binary = bins/azcopy_original(run 10)
	Benchmark 1KiB file: 211.893325ms
	Benchmark 1MiB file: 461.4607ms
	Benchmark 10MiB file: 810.622545ms
	Benchmark 100MiB file: 1.649993952s
	Benchmark 1GiB file: 12.236548842s
Binary = bins/azcopy_changed(run 1)
	Benchmark 1KiB file: 253.721968ms
	Benchmark 1MiB file: 498.897549ms
	Benchmark 10MiB file: 787.010372ms
	Benchmark 100MiB file: 1.381749395s
	Benchmark 1GiB file: 10.446411529s
Binary = bins/azcopy_changed(run 2)
	Benchmark 1KiB file: 252.710169ms
	Benchmark 1MiB file: 531.817803ms
	Benchmark 10MiB file: 829.688513ms
	Benchmark 100MiB file: 1.385873084s
	Benchmark 1GiB file: 8.47119338s
Binary = bins/azcopy_changed(run 3)
	Benchmark 1KiB file: 257.306962ms
	Benchmark 1MiB file: 505.047536ms
	Benchmark 10MiB file: 784.31337ms
	Benchmark 100MiB file: 1.555737854s
	Benchmark 1GiB file: 8.552681344s
Binary = bins/azcopy_changed(run 4)
	Benchmark 1KiB file: 247.846574ms
	Benchmark 1MiB file: 497.231545ms
	Benchmark 10MiB file: 815.651525ms
	Benchmark 100MiB file: 2.697350445s
	Benchmark 1GiB file: 7.516749079s
Binary = bins/azcopy_changed(run 5)
	Benchmark 1KiB file: 252.352667ms
	Benchmark 1MiB file: 501.701337ms
	Benchmark 10MiB file: 707.436865ms
	Benchmark 100MiB file: 1.36936469s
	Benchmark 1GiB file: 9.73502422s
Binary = bins/azcopy_changed(run 6)
	Benchmark 1KiB file: 310.863688ms
	Benchmark 1MiB file: 502.052735ms
	Benchmark 10MiB file: 1.002850071s
	Benchmark 100MiB file: 1.506176604s
	Benchmark 1GiB file: 11.832881097s
Binary = bins/azcopy_changed(run 7)
	Benchmark 1KiB file: 257.951257ms
	Benchmark 1MiB file: 504.845129ms
	Benchmark 10MiB file: 897.192408ms
	Benchmark 100MiB file: 3.660229033s
	Benchmark 1GiB file: 8.277701479s
Binary = bins/azcopy_changed(run 8)
	Benchmark 1KiB file: 248.399669ms
	Benchmark 1MiB file: 510.47592ms
	Benchmark 10MiB file: 660.498819ms
	Benchmark 100MiB file: 983.16489ms
	Benchmark 1GiB file: 9.696608161s
Binary = bins/azcopy_changed(run 9)
	Benchmark 1KiB file: 256.139558ms
	Benchmark 1MiB file: 509.733119ms
	Benchmark 10MiB file: 787.046948ms
	Benchmark 100MiB file: 1.304473257s
	Benchmark 1GiB file: 10.392113698s
Binary = bins/azcopy_changed(run 10)
	Benchmark 1KiB file: 253.185361ms
	Benchmark 1MiB file: 500.357929ms
	Benchmark 10MiB file: 852.302359ms
	Benchmark 100MiB file: 1.555795815s
	Benchmark 1GiB file: 9.234134017s

* Improve comments,  use getErr() instead of old statement, add test for write errors

Added some comment fixes.
Adding some TODOs.
Had an error detection using select that could just use getErr() instead.
Wrote support and test for having a write error.

* Updates to comments provided by ze

* Reduces construction of chunk ids for the commit list, moves azblob_test to azblob

azblob_test should be azblob test, allowing access to private types and removing the need for azblob. as a prefix.  Could find no reason to make as a seperate package in a non-go standard way.

This packages' derivation from the blobstore standard of a new UUID per chunk has merits as discussed with Adele(faster, less memory, possible upload resumes, etc...).  So it was decided to keep it.

However, wanted to make this easier for us to autoincrement ids and provide the list of IDs to commit instead of recreating them at the end at the cost of CPU we didn't have to spend (we were going to spend the memory anyways).  So provided a better way to get the IDs.

This change required changes to the tests.  Most tests use a single blockID.  For those tests we now use a var created on init() that is a UUID+ math.MaxUint32.  That allows us to test the maximum value.

For others, we now use our id type.  This changed one test that was trying to test order, which wasn't necessary.

All tests are passing.

* Update gomod to import uuid an update of adal

* Update go.mod via go tidy command

The adal change was because one of the zt tests uses it.  It always should have been there and won't cause any change in functionality.

errors gets added as an indirecty from check.v1, which it should have always had. This is because check doesn't have a go.mod file.

Adds a minimum version of Go compiler 1.13

* Update go.mod

* Just the mod updates

* Get it back into shape

Some git thing on my side, had to get us hand patched back right.

Co-authored-by: John Doak <jdoak@janama-2.redmond.corp.microsoft.com>
Co-authored-by: John Doak <jdoak@Fan061719.northamerica.corp.microsoft.com>
This commit is contained in:
John Doak 2020-05-01 15:42:05 -07:00 коммит произвёл GitHub
Родитель 68bdb825c9
Коммит c0650f8c2c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
22 изменённых файлов: 10028 добавлений и 1808 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -291,3 +291,4 @@ __pycache__/
*.xsd.cs
vendor/
*.env

Просмотреть файл

@ -1,69 +0,0 @@
package azblob
import "sync/atomic"
// AtomicMorpherInt32 identifies a method passed to and invoked by the AtomicMorphInt32 function.
// The AtomicMorpher callback is passed a startValue and based on this value it returns
// what the new value should be and the result that AtomicMorph should return to its caller.
type atomicMorpherInt32 func(startVal int32) (val int32, morphResult interface{})
const targetAndMorpherMustNotBeNil = "target and morpher must not be nil"
// AtomicMorph atomically morphs target in to new value (and result) as indicated bythe AtomicMorpher callback function.
func atomicMorphInt32(target *int32, morpher atomicMorpherInt32) interface{} {
for {
currentVal := atomic.LoadInt32(target)
desiredVal, morphResult := morpher(currentVal)
if atomic.CompareAndSwapInt32(target, currentVal, desiredVal) {
return morphResult
}
}
}
// AtomicMorpherUint32 identifies a method passed to and invoked by the AtomicMorph function.
// The AtomicMorpher callback is passed a startValue and based on this value it returns
// what the new value should be and the result that AtomicMorph should return to its caller.
type atomicMorpherUint32 func(startVal uint32) (val uint32, morphResult interface{})
// AtomicMorph atomically morphs target in to new value (and result) as indicated bythe AtomicMorpher callback function.
func atomicMorphUint32(target *uint32, morpher atomicMorpherUint32) interface{} {
for {
currentVal := atomic.LoadUint32(target)
desiredVal, morphResult := morpher(currentVal)
if atomic.CompareAndSwapUint32(target, currentVal, desiredVal) {
return morphResult
}
}
}
// AtomicMorpherUint64 identifies a method passed to and invoked by the AtomicMorphUint64 function.
// The AtomicMorpher callback is passed a startValue and based on this value it returns
// what the new value should be and the result that AtomicMorph should return to its caller.
type atomicMorpherInt64 func(startVal int64) (val int64, morphResult interface{})
// AtomicMorph atomically morphs target in to new value (and result) as indicated bythe AtomicMorpher callback function.
func atomicMorphInt64(target *int64, morpher atomicMorpherInt64) interface{} {
for {
currentVal := atomic.LoadInt64(target)
desiredVal, morphResult := morpher(currentVal)
if atomic.CompareAndSwapInt64(target, currentVal, desiredVal) {
return morphResult
}
}
}
// AtomicMorpherUint64 identifies a method passed to and invoked by the AtomicMorphUint64 function.
// The AtomicMorpher callback is passed a startValue and based on this value it returns
// what the new value should be and the result that AtomicMorph should return to its caller.
type atomicMorpherUint64 func(startVal uint64) (val uint64, morphResult interface{})
// AtomicMorph atomically morphs target in to new value (and result) as indicated bythe AtomicMorpher callback function.
func atomicMorphUint64(target *uint64, morpher atomicMorpherUint64) interface{} {
for {
currentVal := atomic.LoadUint64(target)
desiredVal, morphResult := morpher(currentVal)
if atomic.CompareAndSwapUint64(target, currentVal, desiredVal) {
return morphResult
}
}
}

8009
azblob/blob.json Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

228
azblob/chunkwriting.go Normal file
Просмотреть файл

@ -0,0 +1,228 @@
package azblob
import (
"bytes"
"context"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"io"
"sync"
guuid "github.com/google/uuid"
)
// blockWriter provides methods to upload blocks that represent a file to a server and commit them.
// This allows us to provide a local implementation that fakes the server for hermetic testing.
type blockWriter interface {
StageBlock(context.Context, string, io.ReadSeeker, LeaseAccessConditions, []byte) (*BlockBlobStageBlockResponse, error)
CommitBlockList(context.Context, []string, BlobHTTPHeaders, Metadata, BlobAccessConditions) (*BlockBlobCommitBlockListResponse, error)
}
// copyFromReader copies a source io.Reader to blob storage using concurrent uploads.
// TODO(someone): The existing model provides a buffer size and buffer limit as limiting factors. The buffer size is probably
// useless other than needing to be above some number, as the network stack is going to hack up the buffer over some size. The
// max buffers is providing a cap on how much memory we use (by multiplying it times the buffer size) and how many go routines can upload
// at a time. I think having a single max memory dial would be more efficient. We can choose an internal buffer size that works
// well, 4 MiB or 8 MiB, and autoscale to as many goroutines within the memory limit. This gives a single dial to tweak and we can
// choose a max value for the memory setting based on internal transfers within Azure (which will give us the maximum throughput model).
// We can even provide a utility to dial this number in for customer networks to optimize their copies.
func copyFromReader(ctx context.Context, from io.Reader, to blockWriter, o UploadStreamToBlockBlobOptions) (*BlockBlobCommitBlockListResponse, error) {
o.defaults()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cp := &copier{
ctx: ctx,
cancel: cancel,
reader: from,
to: to,
id: newID(),
o: o,
ch: make(chan []byte, 1),
errCh: make(chan error, 1),
buffers: sync.Pool{
New: func() interface{} {
return make([]byte, o.BufferSize)
},
},
}
// Starts the pools of concurrent writers.
cp.wg.Add(o.MaxBuffers)
for i := 0; i < o.MaxBuffers; i++ {
go cp.writer()
}
// Send all our chunks until we get an error.
var err error
for {
if err = cp.sendChunk(); err != nil {
break
}
}
// If the error is not EOF, then we have a problem.
if err != nil && !errors.Is(err, io.EOF) {
return nil, err
}
// Close out our upload.
if err := cp.close(); err != nil {
return nil, err
}
return cp.result, nil
}
// copier streams a file via chunks in parallel from a reader representing a file.
// Do not use directly, instead use copyFromReader().
type copier struct {
// ctx holds the context of a copier. This is normally a faux pas to store a Context in a struct. In this case,
// the copier has the lifetime of a function call, so its fine.
ctx context.Context
cancel context.CancelFunc
// reader is the source to be written to storage.
reader io.Reader
// to is the location we are writing our chunks to.
to blockWriter
id *id
o UploadStreamToBlockBlobOptions
// num is the current chunk we are on.
num int32
// ch is used to pass the next chunk of data from our reader to one of the writers.
ch chan []byte
// errCh is used to hold the first error from our concurrent writers.
errCh chan error
// wg provides a count of how many writers we are waiting to finish.
wg sync.WaitGroup
// buffers provides a pool of chunks that can be reused.
buffers sync.Pool
// result holds the final result from blob storage after we have submitted all chunks.
result *BlockBlobCommitBlockListResponse
}
// getErr returns an error by priority. First, if a function set an error, it returns that error. Next, if the Context has an error
// it returns that error. Otherwise it is nil. getErr supports only returning an error once per copier.
func (c *copier) getErr() error {
select {
case err := <-c.errCh:
return err
default:
}
return c.ctx.Err()
}
// sendChunk reads data from out internal reader, creates a chunk, and sends it to be written via a channel.
// sendChunk returns io.EOF when the reader returns an io.EOF or io.ErrUnexpectedEOF.
func (c *copier) sendChunk() error {
if err := c.getErr(); err != nil {
return err
}
chunk := c.buffers.Get().([]byte)
n, err := io.ReadFull(c.reader, chunk)
chunk = chunk[0:n]
switch {
case err == nil && n == 0:
return nil
case err == nil:
c.ch <- chunk
return nil
case err != nil && (err == io.EOF || err == io.ErrUnexpectedEOF) && n == 0:
return io.EOF
}
if err == io.EOF || err == io.ErrUnexpectedEOF {
c.ch <- chunk
return io.EOF
}
if err := c.getErr(); err != nil {
return err
}
return err
}
// writer writes chunks sent on a channel.
func (c *copier) writer() {
defer c.wg.Done()
for chunk := range c.ch {
if err := c.write(chunk); err != nil {
if !errors.Is(err, context.Canceled) {
select {
case c.errCh <- err:
c.cancel()
default:
}
return
}
}
}
}
// write uploads a chunk to blob storage.
func (c *copier) write(chunk []byte) error {
defer c.buffers.Put(chunk)
if err := c.ctx.Err(); err != nil {
return err
}
_, err := c.to.StageBlock(c.ctx, c.id.next(), bytes.NewReader(chunk), LeaseAccessConditions{}, nil)
if err != nil {
return fmt.Errorf("write error: %w", err)
}
return nil
}
// close commits our blocks to blob storage and closes our writer.
func (c *copier) close() error {
close(c.ch)
c.wg.Wait()
if err := c.getErr(); err != nil {
return err
}
var err error
c.result, err = c.to.CommitBlockList(c.ctx, c.id.issued(), c.o.BlobHTTPHeaders, c.o.Metadata, c.o.AccessConditions)
return err
}
// id allows the creation of unique IDs based on UUID4 + an int32. This autoincrements.
type id struct {
u [64]byte
num uint32
all []string
}
// newID constructs a new id.
func newID() *id {
uu := guuid.New()
u := [64]byte{}
copy(u[:], uu[:])
return &id{u: u}
}
// next returns the next ID. This is not thread-safe.
func (id *id) next() string {
defer func() { id.num++ }()
binary.BigEndian.PutUint32((id.u[len(guuid.UUID{}):]), id.num)
str := base64.StdEncoding.EncodeToString(id.u[:])
id.all = append(id.all, str)
return str
}
// issued returns all ids that have been issued. This returned value shares the internal slice so it is not safe to modify the return.
// The value is only valid until the next time next() is called.
func (id *id) issued() []string {
return id.all
}

273
azblob/chunkwriting_test.go Normal file
Просмотреть файл

@ -0,0 +1,273 @@
package azblob
import (
"context"
"crypto/md5"
"errors"
"fmt"
"io"
"math/rand"
"os"
"path/filepath"
"strings"
"sync/atomic"
"testing"
"time"
)
const finalFileName = "final"
type fakeBlockWriter struct {
path string
block int32
errOnBlock int32
}
func newFakeBlockWriter() *fakeBlockWriter {
f := &fakeBlockWriter{
path: filepath.Join(os.TempDir(), newUUID().String()),
block: -1,
errOnBlock: -1,
}
if err := os.MkdirAll(f.path, 0700); err != nil {
panic(err)
}
return f
}
func (f *fakeBlockWriter) StageBlock(ctx context.Context, blockID string, r io.ReadSeeker, cond LeaseAccessConditions, md5 []byte) (*BlockBlobStageBlockResponse, error) {
n := atomic.AddInt32(&f.block, 1)
if n == f.errOnBlock {
return nil, io.ErrNoProgress
}
blockID = strings.Replace(blockID, "/", "slash", -1)
fp, err := os.OpenFile(filepath.Join(f.path, blockID), os.O_CREATE+os.O_WRONLY, 0600)
if err != nil {
return nil, fmt.Errorf("could not create a stage block file: %s", err)
}
defer fp.Close()
if _, err := io.Copy(fp, r); err != nil {
return nil, err
}
return &BlockBlobStageBlockResponse{}, nil
}
func (f *fakeBlockWriter) CommitBlockList(ctx context.Context, blockIDs []string, headers BlobHTTPHeaders, meta Metadata, access BlobAccessConditions) (*BlockBlobCommitBlockListResponse, error) {
dst, err := os.OpenFile(filepath.Join(f.path, finalFileName), os.O_CREATE+os.O_WRONLY, 0600)
if err != nil {
return nil, err
}
defer dst.Close()
for _, id := range blockIDs {
id = strings.Replace(id, "/", "slash", -1)
src, err := os.Open(filepath.Join(f.path, id))
if err != nil {
return nil, fmt.Errorf("could not combine chunk %s: %s", id, err)
}
_, err = io.Copy(dst, src)
src.Close()
if err != nil {
return nil, fmt.Errorf("problem writing final file from chunks: %s", err)
}
}
return &BlockBlobCommitBlockListResponse{}, nil
}
func (f *fakeBlockWriter) cleanup() {
os.RemoveAll(f.path)
}
func (f *fakeBlockWriter) final() string {
return filepath.Join(f.path, finalFileName)
}
func createSrcFile(size int) (string, error) {
p := filepath.Join(os.TempDir(), newUUID().String())
fp, err := os.OpenFile(p, os.O_CREATE+os.O_WRONLY, 0600)
if err != nil {
return "", fmt.Errorf("could not create source file: %s", err)
}
defer fp.Close()
lr := &io.LimitedReader{R: rand.New(rand.NewSource(time.Now().UnixNano())), N: int64(size)}
copied, err := io.Copy(fp, lr)
switch {
case err != nil && err != io.EOF:
return "", fmt.Errorf("copying %v: %s", size, err)
case copied != int64(size):
return "", fmt.Errorf("copying %v: copied %d bytes, expected %d", size, copied, size)
}
return p, nil
}
func fileMD5(p string) string {
f, err := os.Open(p)
if err != nil {
panic(err)
}
defer f.Close()
h := md5.New()
if _, err := io.Copy(h, f); err != nil {
panic(err)
}
return fmt.Sprintf("%x", h.Sum(nil))
}
func TestGetErr(t *testing.T) {
t.Parallel()
canceled, cancel := context.WithCancel(context.Background())
cancel()
err := errors.New("error")
tests := []struct {
desc string
ctx context.Context
err error
want error
}{
{"No errors", context.Background(), nil, nil},
{"Context was cancelled", canceled, nil, context.Canceled},
{"Context was cancelled but had error", canceled, err, err},
{"Err returned", context.Background(), err, err},
}
for _, test := range tests {
c := copier{errCh: make(chan error, 1), ctx: test.ctx}
if test.err != nil {
c.errCh <- test.err
}
got := c.getErr()
if test.want != got {
t.Errorf("TestGetErr(%s): got %v, want %v", test.desc, got, test.want)
}
}
}
func TestCopyFromReader(t *testing.T) {
t.Parallel()
canceled, cancel := context.WithCancel(context.Background())
cancel()
tests := []struct {
desc string
ctx context.Context
o UploadStreamToBlockBlobOptions
fileSize int
uploadErr bool
err bool
}{
{
desc: "context was cancelled",
ctx: canceled,
err: true,
},
{
desc: "Send file(0 KiB) with default UploadStreamToBlockBlobOptions",
ctx: context.Background(),
fileSize: 0,
},
{
desc: "Send file(10 KiB) with default UploadStreamToBlockBlobOptions",
ctx: context.Background(),
fileSize: 10 * 1024,
},
{
desc: "Send file(10 KiB) with default UploadStreamToBlockBlobOptions set to azcopy settings",
ctx: context.Background(),
fileSize: 10 * 1024,
o: UploadStreamToBlockBlobOptions{MaxBuffers: 5, BufferSize: 8 * 1024 * 1024},
},
{
desc: "Send file(1 MiB) with default UploadStreamToBlockBlobOptions",
ctx: context.Background(),
fileSize: _1MiB,
},
{
desc: "Send file(1 MiB) with default UploadStreamToBlockBlobOptions set to azcopy settings",
ctx: context.Background(),
fileSize: _1MiB,
o: UploadStreamToBlockBlobOptions{MaxBuffers: 5, BufferSize: 8 * 1024 * 1024},
},
{
desc: "Send file(1.5 MiB) with default UploadStreamToBlockBlobOptions",
ctx: context.Background(),
fileSize: _1MiB + 500*1024,
},
{
desc: "Send file(1.5 MiB) with 2 writers",
ctx: context.Background(),
fileSize: _1MiB + 500*1024 + 1,
o: UploadStreamToBlockBlobOptions{MaxBuffers: 2},
},
{
desc: "Send file(12 MiB) with 3 writers and 1 MiB buffer and a write error",
ctx: context.Background(),
fileSize: 12 * _1MiB,
o: UploadStreamToBlockBlobOptions{MaxBuffers: 2, BufferSize: _1MiB},
uploadErr: true,
err: true,
},
{
desc: "Send file(12 MiB) with 3 writers and 1.5 MiB buffer",
ctx: context.Background(),
fileSize: 12 * _1MiB,
o: UploadStreamToBlockBlobOptions{MaxBuffers: 2, BufferSize: _1MiB + .5*_1MiB},
},
{
desc: "Send file(12 MiB) with default UploadStreamToBlockBlobOptions set to azcopy settings",
ctx: context.Background(),
fileSize: 12 * _1MiB,
o: UploadStreamToBlockBlobOptions{MaxBuffers: 5, BufferSize: 8 * 1024 * 1024},
},
}
for _, test := range tests {
p, err := createSrcFile(test.fileSize)
if err != nil {
panic(err)
}
defer os.Remove(p)
from, err := os.Open(p)
if err != nil {
panic(err)
}
br := newFakeBlockWriter()
defer br.cleanup()
if test.uploadErr {
br.errOnBlock = 1
}
_, err = copyFromReader(test.ctx, from, br, test.o)
switch {
case err == nil && test.err:
t.Errorf("TestCopyFromReader(%s): got err == nil, want err != nil", test.desc)
continue
case err != nil && !test.err:
t.Errorf("TestCopyFromReader(%s): got err == %s, want err == nil", test.desc, err)
continue
case err != nil:
continue
}
want := fileMD5(p)
got := fileMD5(br.final())
if got != want {
t.Errorf("TestCopyFromReader(%s): MD5 not the same: got %s, want %s", test.desc, got, want)
}
}
}

Просмотреть файл

@ -352,192 +352,44 @@ func DoBatchTransfer(ctx context.Context, o BatchTransferOptions) error {
////////////////////////////////////////////////////////////////////////////////////////////////
const _1MiB = 1024 * 1024
type UploadStreamToBlockBlobOptions struct {
BufferSize int
// BufferSize sizes the buffer used to read data from source. If < 1 MiB, defaults to 1 MiB.
BufferSize int
// MaxBuffers defines the number of simultaneous uploads will be performed to upload the file.
MaxBuffers int
BlobHTTPHeaders BlobHTTPHeaders
Metadata Metadata
AccessConditions BlobAccessConditions
}
func (u *UploadStreamToBlockBlobOptions) defaults() {
if u.MaxBuffers == 0 {
u.MaxBuffers = 1
}
if u.BufferSize < _1MiB {
u.BufferSize = _1MiB
}
}
// UploadStreamToBlockBlob copies the file held in io.Reader to the Blob at blockBlobURL.
// A Context deadline or cancellation will cause this to error.
func UploadStreamToBlockBlob(ctx context.Context, reader io.Reader, blockBlobURL BlockBlobURL,
o UploadStreamToBlockBlobOptions) (CommonResponse, error) {
result, err := uploadStream(ctx, reader,
UploadStreamOptions{BufferSize: o.BufferSize, MaxBuffers: o.MaxBuffers},
&uploadStreamToBlockBlobOptions{b: blockBlobURL, o: o, blockIDPrefix: newUUID()})
o.defaults()
result, err := copyFromReader(ctx, reader, blockBlobURL, o)
if err != nil {
return nil, err
}
return result.(CommonResponse), nil
}
type uploadStreamToBlockBlobOptions struct {
b BlockBlobURL
o UploadStreamToBlockBlobOptions
blockIDPrefix uuid // UUID used with all blockIDs
maxBlockNum uint32 // defaults to 0
firstBlock []byte // Used only if maxBlockNum is 0
}
func (t *uploadStreamToBlockBlobOptions) start(ctx context.Context) (interface{}, error) {
return nil, nil
}
func (t *uploadStreamToBlockBlobOptions) chunk(ctx context.Context, num uint32, buffer []byte) error {
if num == 0 {
t.firstBlock = buffer
// If whole payload fits in 1 block, don't stage it; End will upload it with 1 I/O operation
// If the payload is exactly the same size as the buffer, there may be more content coming in.
if len(buffer) < t.o.BufferSize {
return nil
}
}
// Else, upload a staged block...
atomicMorphUint32(&t.maxBlockNum, func(startVal uint32) (val uint32, morphResult interface{}) {
// Atomically remember (in t.numBlocks) the maximum block num we've ever seen
if startVal < num {
return num, nil
}
return startVal, nil
})
blockID := newUuidBlockID(t.blockIDPrefix).WithBlockNumber(num).ToBase64()
_, err := t.b.StageBlock(ctx, blockID, bytes.NewReader(buffer), LeaseAccessConditions{}, nil)
return err
}
func (t *uploadStreamToBlockBlobOptions) end(ctx context.Context) (interface{}, error) {
// If the first block had the exact same size as the buffer
// we would have staged it as a block thinking that there might be more data coming
if t.maxBlockNum == 0 && len(t.firstBlock) != t.o.BufferSize {
// If whole payload fits in 1 block (block #0), upload it with 1 I/O operation
return t.b.Upload(ctx, bytes.NewReader(t.firstBlock),
t.o.BlobHTTPHeaders, t.o.Metadata, t.o.AccessConditions)
}
// Multiple blocks staged, commit them all now
blockID := newUuidBlockID(t.blockIDPrefix)
blockIDs := make([]string, t.maxBlockNum+1)
for bn := uint32(0); bn <= t.maxBlockNum; bn++ {
blockIDs[bn] = blockID.WithBlockNumber(bn).ToBase64()
}
return t.b.CommitBlockList(ctx, blockIDs, t.o.BlobHTTPHeaders, t.o.Metadata, t.o.AccessConditions)
}
////////////////////////////////////////////////////////////////////////////////////////////////////
type iTransfer interface {
start(ctx context.Context) (interface{}, error)
chunk(ctx context.Context, num uint32, buffer []byte) error
end(ctx context.Context) (interface{}, error)
return result, nil
}
// UploadStreamOptions (defunct) was used internally. This will be removed or made private in a future version.
type UploadStreamOptions struct {
MaxBuffers int
BufferSize int
}
type firstErr struct {
lock sync.Mutex
finalError error
}
func (fe *firstErr) set(err error) {
fe.lock.Lock()
if fe.finalError == nil {
fe.finalError = err
}
fe.lock.Unlock()
}
func (fe *firstErr) get() (err error) {
fe.lock.Lock()
err = fe.finalError
fe.lock.Unlock()
return
}
func uploadStream(ctx context.Context, reader io.Reader, o UploadStreamOptions, t iTransfer) (interface{}, error) {
firstErr := firstErr{}
ctx, cancel := context.WithCancel(ctx) // New context so that any failure cancels everything
defer cancel()
wg := sync.WaitGroup{} // Used to know when all outgoing messages have finished processing
type OutgoingMsg struct {
chunkNum uint32
buffer []byte
}
// Create a channel to hold the buffers usable for incoming datsa
incoming := make(chan []byte, o.MaxBuffers)
outgoing := make(chan OutgoingMsg, o.MaxBuffers) // Channel holding outgoing buffers
if result, err := t.start(ctx); err != nil {
return result, err
}
numBuffers := 0 // The number of buffers & out going goroutines created so far
injectBuffer := func() {
// For each Buffer, create it and a goroutine to upload it
incoming <- make([]byte, o.BufferSize) // Add the new buffer to the incoming channel so this goroutine can from the reader into it
numBuffers++
go func() {
for outgoingMsg := range outgoing {
// Upload the outgoing buffer
err := t.chunk(ctx, outgoingMsg.chunkNum, outgoingMsg.buffer)
wg.Done() // Indicate this buffer was sent
if nil != err {
// NOTE: finalErr could be assigned to multiple times here which is OK,
// some error will be returned.
firstErr.set(err)
cancel()
}
incoming <- outgoingMsg.buffer // The goroutine reading from the stream can reuse this buffer now
}
}()
}
injectBuffer() // Create our 1st buffer & outgoing goroutine
// This goroutine grabs a buffer, reads from the stream into the buffer,
// and inserts the buffer into the outgoing channel to be uploaded
for c := uint32(0); true; c++ { // Iterate once per chunk
var buffer []byte
if numBuffers < o.MaxBuffers {
select {
// We're not at max buffers, see if a previously-created buffer is available
case buffer = <-incoming:
break
default:
// No buffer available; inject a new buffer & go routine to process it
injectBuffer()
buffer = <-incoming // Grab the just-injected buffer
}
} else {
// We are at max buffers, block until we get to reuse one
buffer = <-incoming
}
n, err := io.ReadFull(reader, buffer)
if err != nil { // Less than len(buffer) bytes were read
buffer = buffer[:n] // Make slice match the # of read bytes
}
if len(buffer) > 0 {
// Buffer not empty, upload it
wg.Add(1) // We're posting a buffer to be sent
outgoing <- OutgoingMsg{chunkNum: c, buffer: buffer}
}
if err != nil { // The reader is done, no more outgoing buffers
if err == io.EOF || err == io.ErrUnexpectedEOF {
err = nil // This function does NOT return an error if io.ReadFull returns io.EOF or io.ErrUnexpectedEOF
} else {
firstErr.set(err)
}
break
}
}
// NOTE: Don't close the incoming channel because the outgoing goroutines post buffers into it when they are done
close(outgoing) // Make all the outgoing goroutines terminate when this channel is empty
wg.Wait() // Wait for all pending outgoing messages to complete
err := firstErr.get()
if err == nil {
// If no error, after all blocks uploaded, commit them to the blob & return the result
return t.end(ctx)
}
return nil, err
MaxBuffers int
}

Просмотреть файл

@ -5,9 +5,6 @@ import (
"io"
"net/url"
"encoding/base64"
"encoding/binary"
"github.com/Azure/azure-pipeline-go/pipeline"
)
@ -135,56 +132,3 @@ func (bb BlockBlobURL) CopyFromURL(ctx context.Context, source url.URL, metadata
dstIfMatchETag, dstIfNoneMatchETag,
dstLeaseID, nil, srcContentMD5)
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
type BlockID [64]byte
func (blockID BlockID) ToBase64() string {
return base64.StdEncoding.EncodeToString(blockID[:])
}
func (blockID *BlockID) FromBase64(s string) error {
*blockID = BlockID{} // Zero out the block ID
_, err := base64.StdEncoding.Decode(blockID[:], ([]byte)(s))
return err
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
type uuidBlockID BlockID
func (ubi uuidBlockID) UUID() uuid {
u := uuid{}
copy(u[:], ubi[:len(u)])
return u
}
func (ubi uuidBlockID) Number() uint32 {
return binary.BigEndian.Uint32(ubi[len(uuid{}):])
}
func newUuidBlockID(u uuid) uuidBlockID {
ubi := uuidBlockID{} // Create a new uuidBlockID
copy(ubi[:len(u)], u[:]) // Copy the specified UUID into it
// Block number defaults to 0
return ubi
}
func (ubi *uuidBlockID) SetUUID(u uuid) *uuidBlockID {
copy(ubi[:len(u)], u[:])
return ubi
}
func (ubi uuidBlockID) WithBlockNumber(blockNumber uint32) uuidBlockID {
binary.BigEndian.PutUint32(ubi[len(uuid{}):], blockNumber) // Put block number after UUID
return ubi // Return the passed-in copy
}
func (ubi uuidBlockID) ToBase64() string {
return BlockID(ubi).ToBase64()
}
func (ubi *uuidBlockID) FromBase64(s string) error {
return (*BlockID)(ubi).FromBase64(s)
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,4 @@
package azblob_test
package azblob
import (
"context"
@ -8,7 +8,6 @@ import (
"sync/atomic"
"time"
"github.com/Azure/azure-storage-blob-go/azblob"
chk "gopkg.in/check.v1"
)
@ -35,15 +34,15 @@ func performUploadStreamToBlockBlobTest(c *chk.C, blobSize, bufferSize, maxBuffe
blobContentReader, blobData := getRandomDataAndReader(blobSize)
// Perform UploadStreamToBlockBlob
uploadResp, err := azblob.UploadStreamToBlockBlob(ctx, blobContentReader, blobURL,
azblob.UploadStreamToBlockBlobOptions{BufferSize: bufferSize, MaxBuffers: maxBuffers})
uploadResp, err := UploadStreamToBlockBlob(ctx, blobContentReader, blobURL,
UploadStreamToBlockBlobOptions{BufferSize: bufferSize, MaxBuffers: maxBuffers})
// Assert that upload was successful
c.Assert(err, chk.Equals, nil)
c.Assert(uploadResp.Response().StatusCode, chk.Equals, 201)
// Download the blob to verify
downloadResponse, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
downloadResponse, err := blobURL.Download(ctx, 0, 0, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
// Assert that the content is correct
@ -108,8 +107,8 @@ func performUploadAndDownloadFileTest(c *chk.C, fileSize, blockSize, parallelism
blockBlobURL, _ := getBlockBlobURL(c, containerURL)
// Upload the file to a block blob
response, err := azblob.UploadFileToBlockBlob(context.Background(), file, blockBlobURL,
azblob.UploadToBlockBlobOptions{
response, err := UploadFileToBlockBlob(context.Background(), file, blockBlobURL,
UploadToBlockBlobOptions{
BlockSize: int64(blockSize),
Parallelism: uint16(parallelism),
// If Progress is non-nil, this function is called periodically as bytes are uploaded.
@ -128,9 +127,9 @@ func performUploadAndDownloadFileTest(c *chk.C, fileSize, blockSize, parallelism
defer os.Remove(destFileName)
// Perform download
err = azblob.DownloadBlobToFile(context.Background(), blockBlobURL.BlobURL, int64(downloadOffset), int64(downloadCount),
err = DownloadBlobToFile(context.Background(), blockBlobURL.BlobURL, int64(downloadOffset), int64(downloadCount),
destFile,
azblob.DownloadFromBlobOptions{
DownloadFromBlobOptions{
BlockSize: int64(blockSize),
Parallelism: uint16(parallelism),
// If Progress is non-nil, this function is called periodically as bytes are uploaded.
@ -143,7 +142,7 @@ func performUploadAndDownloadFileTest(c *chk.C, fileSize, blockSize, parallelism
// Assert downloaded data is consistent
var destBuffer []byte
if downloadCount == azblob.CountToEnd {
if downloadCount == CountToEnd {
destBuffer = make([]byte, fileSize-downloadOffset)
} else {
destBuffer = make([]byte, downloadCount)
@ -233,8 +232,8 @@ func performUploadAndDownloadBufferTest(c *chk.C, blobSize, blockSize, paralleli
blockBlobURL, _ := getBlockBlobURL(c, containerURL)
// Pass the Context, stream, stream size, block blob URL, and options to StreamToBlockBlob
response, err := azblob.UploadBufferToBlockBlob(context.Background(), bytesToUpload, blockBlobURL,
azblob.UploadToBlockBlobOptions{
response, err := UploadBufferToBlockBlob(context.Background(), bytesToUpload, blockBlobURL,
UploadToBlockBlobOptions{
BlockSize: int64(blockSize),
Parallelism: uint16(parallelism),
// If Progress is non-nil, this function is called periodically as bytes are uploaded.
@ -247,16 +246,16 @@ func performUploadAndDownloadBufferTest(c *chk.C, blobSize, blockSize, paralleli
// Set up buffer to download the blob to
var destBuffer []byte
if downloadCount == azblob.CountToEnd {
if downloadCount == CountToEnd {
destBuffer = make([]byte, blobSize-downloadOffset)
} else {
destBuffer = make([]byte, downloadCount)
}
// Download the blob to a buffer
err = azblob.DownloadBlobToBuffer(context.Background(), blockBlobURL.BlobURL, int64(downloadOffset), int64(downloadCount),
destBuffer, azblob.DownloadFromBlobOptions{
AccessConditions: azblob.BlobAccessConditions{},
err = DownloadBlobToBuffer(context.Background(), blockBlobURL.BlobURL, int64(downloadOffset), int64(downloadCount),
destBuffer, DownloadFromBlobOptions{
AccessConditions: BlobAccessConditions{},
BlockSize: int64(blockSize),
Parallelism: uint16(parallelism),
// If Progress is non-nil, this function is called periodically as bytes are uploaded.
@ -358,7 +357,7 @@ func (s *aztestsSuite) TestBasicDoBatchTransfer(c *chk.C) {
totalSizeCount := int64(0)
runCount := int64(0)
err := azblob.DoBatchTransfer(ctx, azblob.BatchTransferOptions{
err := DoBatchTransfer(ctx, BatchTransferOptions{
TransferSize: test.transferSize,
ChunkSize: test.chunkSize,
Parallelism: test.parallelism,
@ -399,7 +398,7 @@ func (s *aztestsSuite) TestDoBatchTransferWithError(c *chk.C) {
mmf := mockMMF{failHandle: c}
expectedFirstError := errors.New("#3 means trouble")
err := azblob.DoBatchTransfer(ctx, azblob.BatchTransferOptions{
err := DoBatchTransfer(ctx, BatchTransferOptions{
TransferSize: 5,
ChunkSize: 1,
Parallelism: 5,

Просмотреть файл

@ -1,4 +1,4 @@
package azblob_test
package azblob
import (
"context"
@ -12,7 +12,6 @@ import (
chk "gopkg.in/check.v1"
"github.com/Azure/azure-pipeline-go/pipeline"
"github.com/Azure/azure-storage-blob-go/azblob"
)
// For testing docs, see: https://labix.org/gocheck
@ -147,8 +146,8 @@ func (p *retryTestPolicy) Do(ctx context.Context, request pipeline.Request) (res
func testRetryTestScenario(c *chk.C, scenario retryTestScenario) {
u, _ := url.Parse("http://PrimaryDC")
retryOptions := azblob.RetryOptions{
Policy: azblob.RetryPolicyExponential,
retryOptions := RetryOptions{
Policy: RetryPolicyExponential,
MaxTries: 6,
TryTimeout: 2 * time.Second,
RetryDelay: 1 * time.Second,
@ -160,7 +159,7 @@ func testRetryTestScenario(c *chk.C, scenario retryTestScenario) {
ctx, cancel := context.WithTimeout(ctx, 64 /*2^MaxTries(6)*/ *retryOptions.TryTimeout)
retrytestPolicyFactory := newRetryTestPolicyFactory(c, scenario, retryOptions.MaxTries, cancel)
factories := [...]pipeline.Factory{
azblob.NewRetryPolicyFactory(retryOptions),
NewRetryPolicyFactory(retryOptions),
retrytestPolicyFactory,
}
p := pipeline.NewPipeline(factories[:], pipeline.Options{})

Просмотреть файл

@ -1,4 +1,4 @@
package azblob_test
package azblob
import (
"context"
@ -10,7 +10,6 @@ import (
"net/http"
"time"
"github.com/Azure/azure-storage-blob-go/azblob"
chk "gopkg.in/check.v1"
)
@ -68,7 +67,7 @@ func (r *perByteReader) Read(b []byte) (n int, err error) {
// error
select {
case <-r.closeChannel:
return n, errors.New(azblob.ReadOnClosedBodyMessage)
return n, errors.New(ReadOnClosedBodyMessage)
case <-time.After(r.sleepDuration):
return n, nil
}
@ -114,7 +113,7 @@ func (s *aztestsSuite) TestRetryReaderReadWithRetry(c *chk.C) {
body.doInjectTimes = 1
body.injectedError = &net.DNSError{IsTemporary: true}
getter := func(ctx context.Context, info azblob.HTTPGetterInfo) (*http.Response, error) {
getter := func(ctx context.Context, info HTTPGetterInfo) (*http.Response, error) {
r := http.Response{}
body.currentByteIndex = int(info.Offset)
r.Body = body
@ -122,15 +121,15 @@ func (s *aztestsSuite) TestRetryReaderReadWithRetry(c *chk.C) {
return &r, nil
}
httpGetterInfo := azblob.HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}
httpGetterInfo := HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}
initResponse, err := getter(context.Background(), httpGetterInfo)
c.Assert(err, chk.IsNil)
rrOptions := azblob.RetryReaderOptions{MaxRetryRequests: 1}
rrOptions := RetryReaderOptions{MaxRetryRequests: 1}
if logThisRun {
rrOptions.NotifyFailedRead = failureMethod
}
retryReader := azblob.NewRetryReader(context.Background(), initResponse, httpGetterInfo, rrOptions, getter)
retryReader := NewRetryReader(context.Background(), initResponse, httpGetterInfo, rrOptions, getter)
// should fail and succeed through retry
can := make([]byte, 1)
@ -181,7 +180,7 @@ func (s *aztestsSuite) TestRetryReaderReadNegativeNormalFail(c *chk.C) {
startResponse := http.Response{}
startResponse.Body = body
getter := func(ctx context.Context, info azblob.HTTPGetterInfo) (*http.Response, error) {
getter := func(ctx context.Context, info HTTPGetterInfo) (*http.Response, error) {
r := http.Response{}
body.currentByteIndex = int(info.Offset)
r.Body = body
@ -189,10 +188,10 @@ func (s *aztestsSuite) TestRetryReaderReadNegativeNormalFail(c *chk.C) {
return &r, nil
}
rrOptions := azblob.RetryReaderOptions{
rrOptions := RetryReaderOptions{
MaxRetryRequests: 1,
NotifyFailedRead: failureMethod}
retryReader := azblob.NewRetryReader(context.Background(), &startResponse, azblob.HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}, rrOptions, getter)
retryReader := NewRetryReader(context.Background(), &startResponse, HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}, rrOptions, getter)
// should fail
can := make([]byte, 1)
@ -221,7 +220,7 @@ func (s *aztestsSuite) TestRetryReaderReadCount0(c *chk.C) {
startResponse := http.Response{}
startResponse.Body = body
getter := func(ctx context.Context, info azblob.HTTPGetterInfo) (*http.Response, error) {
getter := func(ctx context.Context, info HTTPGetterInfo) (*http.Response, error) {
r := http.Response{}
body.currentByteIndex = int(info.Offset)
r.Body = body
@ -229,7 +228,7 @@ func (s *aztestsSuite) TestRetryReaderReadCount0(c *chk.C) {
return &r, nil
}
retryReader := azblob.NewRetryReader(context.Background(), &startResponse, azblob.HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}, azblob.RetryReaderOptions{MaxRetryRequests: 1}, getter)
retryReader := NewRetryReader(context.Background(), &startResponse, HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}, RetryReaderOptions{MaxRetryRequests: 1}, getter)
// should consume the only byte
can := make([]byte, 1)
@ -254,7 +253,7 @@ func (s *aztestsSuite) TestRetryReaderReadNegativeNonRetriableError(c *chk.C) {
startResponse := http.Response{}
startResponse.Body = body
getter := func(ctx context.Context, info azblob.HTTPGetterInfo) (*http.Response, error) {
getter := func(ctx context.Context, info HTTPGetterInfo) (*http.Response, error) {
r := http.Response{}
body.currentByteIndex = int(info.Offset)
r.Body = body
@ -262,7 +261,7 @@ func (s *aztestsSuite) TestRetryReaderReadNegativeNonRetriableError(c *chk.C) {
return &r, nil
}
retryReader := azblob.NewRetryReader(context.Background(), &startResponse, azblob.HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}, azblob.RetryReaderOptions{MaxRetryRequests: 2}, getter)
retryReader := NewRetryReader(context.Background(), &startResponse, HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}, RetryReaderOptions{MaxRetryRequests: 2}, getter)
dest := make([]byte, 1)
_, err := retryReader.Read(dest)
@ -289,7 +288,7 @@ func (s *aztestsSuite) TestRetryReaderReadWithForcedRetry(c *chk.C) {
sleepDuration := 100 * time.Millisecond
randBytes := make([]byte, byteCount)
_, _ = rand.Read(randBytes)
getter := func(ctx context.Context, info azblob.HTTPGetterInfo) (*http.Response, error) {
getter := func(ctx context.Context, info HTTPGetterInfo) (*http.Response, error) {
body := newSingleUsePerByteReader(randBytes) // make new one every time, since we force closes in this test, and its unusable after a close
body.sleepDuration = sleepDuration
r := http.Response{}
@ -299,13 +298,13 @@ func (s *aztestsSuite) TestRetryReaderReadWithForcedRetry(c *chk.C) {
return &r, nil
}
httpGetterInfo := azblob.HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}
httpGetterInfo := HTTPGetterInfo{Offset: 0, Count: int64(byteCount)}
initResponse, err := getter(context.Background(), httpGetterInfo)
c.Assert(err, chk.IsNil)
rrOptions := azblob.RetryReaderOptions{MaxRetryRequests: 2, TreatEarlyCloseAsError: !enableRetryOnEarlyClose}
rrOptions := RetryReaderOptions{MaxRetryRequests: 2, TreatEarlyCloseAsError: !enableRetryOnEarlyClose}
rrOptions.NotifyFailedRead = failureMethod
retryReader := azblob.NewRetryReader(context.Background(), initResponse, httpGetterInfo, rrOptions, getter)
retryReader := NewRetryReader(context.Background(), initResponse, httpGetterInfo, rrOptions, getter)
// set up timed cancellation from separate goroutine
go func() {

Просмотреть файл

@ -1,11 +1,11 @@
package azblob_test
package azblob
import (
"bytes"
"github.com/Azure/azure-storage-blob-go/azblob"
chk "gopkg.in/check.v1"
"strings"
"time"
chk "gopkg.in/check.v1"
)
func (s *aztestsSuite) TestSnapshotSAS(c *chk.C) {
@ -14,8 +14,8 @@ func (s *aztestsSuite) TestSnapshotSAS(c *chk.C) {
containerURL, containerName := getContainerURL(c, bsu)
blobURL, blobName := getBlockBlobURL(c, containerURL)
_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessNone)
defer containerURL.Delete(ctx, azblob.ContainerAccessConditions{})
_, err := containerURL.Create(ctx, Metadata{}, PublicAccessNone)
defer containerURL.Delete(ctx, ContainerAccessConditions{})
if err != nil {
c.Fatal(err)
}
@ -24,19 +24,19 @@ func (s *aztestsSuite) TestSnapshotSAS(c *chk.C) {
burl := containerURL.NewBlockBlobURL(blobName)
data := "Hello world!"
_, err = burl.Upload(ctx, strings.NewReader(data), azblob.BlobHTTPHeaders{ContentType: "text/plain"}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err = burl.Upload(ctx, strings.NewReader(data), BlobHTTPHeaders{ContentType: "text/plain"}, Metadata{}, BlobAccessConditions{})
if err != nil {
c.Fatal(err)
}
//Create a snapshot & URL
createSnapshot, err := burl.CreateSnapshot(ctx, azblob.Metadata{}, azblob.BlobAccessConditions{})
createSnapshot, err := burl.CreateSnapshot(ctx, Metadata{}, BlobAccessConditions{})
if err != nil {
c.Fatal(err)
}
//Format snapshot time
snapTime, err := time.Parse(azblob.SnapshotTimeFormat, createSnapshot.Snapshot())
snapTime, err := time.Parse(SnapshotTimeFormat, createSnapshot.Snapshot())
if err != nil {
c.Fatal(err)
}
@ -49,40 +49,40 @@ func (s *aztestsSuite) TestSnapshotSAS(c *chk.C) {
}
//Create SAS query
snapSASQueryParams, err := azblob.BlobSASSignatureValues{
snapSASQueryParams, err := BlobSASSignatureValues{
StartTime: currentTime,
ExpiryTime: currentTime.Add(48 * time.Hour),
SnapshotTime: snapTime,
Permissions: "racwd",
ContainerName: containerName,
BlobName: blobName,
Protocol: azblob.SASProtocolHTTPS,
Protocol: SASProtocolHTTPS,
}.NewSASQueryParameters(credential)
if err != nil {
c.Fatal(err)
}
//Attach SAS query to block blob URL
p := azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
snapParts := azblob.NewBlobURLParts(blobURL.URL())
p := NewPipeline(NewAnonymousCredential(), PipelineOptions{})
snapParts := NewBlobURLParts(blobURL.URL())
snapParts.SAS = snapSASQueryParams
sburl := azblob.NewBlockBlobURL(snapParts.URL(), p)
sburl := NewBlockBlobURL(snapParts.URL(), p)
//Test the snapshot
downloadResponse, err := sburl.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
downloadResponse, err := sburl.Download(ctx, 0, 0, BlobAccessConditions{}, false)
if err != nil {
c.Fatal(err)
}
downloadedData := &bytes.Buffer{}
reader := downloadResponse.Body(azblob.RetryReaderOptions{})
reader := downloadResponse.Body(RetryReaderOptions{})
downloadedData.ReadFrom(reader)
reader.Close()
c.Assert(data, chk.Equals, downloadedData.String())
//Try to delete snapshot -------------------------------------------------------------------------------------------
_, err = sburl.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
_, err = sburl.Delete(ctx, DeleteSnapshotsOptionNone, BlobAccessConditions{})
if err != nil { //This shouldn't fail.
c.Fatal(err)
}
@ -91,16 +91,16 @@ func (s *aztestsSuite) TestSnapshotSAS(c *chk.C) {
//If this succeeds, it means a normal SAS token was created.
fsburl := containerURL.NewBlockBlobURL("failsnap")
_, err = fsburl.Upload(ctx, strings.NewReader(data), azblob.BlobHTTPHeaders{ContentType: "text/plain"}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err = fsburl.Upload(ctx, strings.NewReader(data), BlobHTTPHeaders{ContentType: "text/plain"}, Metadata{}, BlobAccessConditions{})
if err != nil {
c.Fatal(err) //should succeed to create the blob via normal auth means
}
fsburlparts := azblob.NewBlobURLParts(fsburl.URL())
fsburlparts := NewBlobURLParts(fsburl.URL())
fsburlparts.SAS = snapSASQueryParams
fsburl = azblob.NewBlockBlobURL(fsburlparts.URL(), p) //re-use fsburl as we don't need the sharedkey version anymore
fsburl = NewBlockBlobURL(fsburlparts.URL(), p) //re-use fsburl as we don't need the sharedkey version anymore
resp, err := fsburl.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
resp, err := fsburl.Delete(ctx, DeleteSnapshotsOptionNone, BlobAccessConditions{})
if err == nil {
c.Fatal(resp) //This SHOULD fail. Otherwise we have a normal SAS token...
}

Просмотреть файл

@ -1,4 +1,4 @@
package azblob_test
package azblob
import (
"bytes"
@ -20,7 +20,6 @@ import (
"math/rand"
"github.com/Azure/azure-pipeline-go/pipeline"
"github.com/Azure/azure-storage-blob-go/azblob"
"github.com/Azure/go-autorest/autorest/adal"
)
@ -35,7 +34,7 @@ type aztestsSuite struct{}
var _ = chk.Suite(&aztestsSuite{})
func (s *aztestsSuite) TestRetryPolicyRetryReadsFromSecondaryHostField(c *chk.C) {
_, found := reflect.TypeOf(azblob.RetryOptions{}).FieldByName("RetryReadsFromSecondaryHost")
_, found := reflect.TypeOf(RetryOptions{}).FieldByName("RetryReadsFromSecondaryHost")
if !found {
// Make sure the RetryOption was not erroneously overwritten
c.Fatal("RetryOption's RetryReadsFromSecondaryHost field must exist in the Blob SDK - uncomment it and make sure the field is returned from the retryReadsFromSecondaryHost() method too!")
@ -51,7 +50,7 @@ const (
)
var ctx = context.Background()
var basicHeaders = azblob.BlobHTTPHeaders{
var basicHeaders = BlobHTTPHeaders{
ContentType: "my_type",
ContentDisposition: "my_disposition",
CacheControl: "control",
@ -60,7 +59,7 @@ var basicHeaders = azblob.BlobHTTPHeaders{
ContentEncoding: "my_encoding",
}
var basicMetadata = azblob.Metadata{"foo": "bar"}
var basicMetadata = Metadata{"foo": "bar"}
type testPipeline struct{}
@ -104,28 +103,28 @@ func generateBlobName() string {
return generateName(blobPrefix)
}
func getContainerURL(c *chk.C, bsu azblob.ServiceURL) (container azblob.ContainerURL, name string) {
func getContainerURL(c *chk.C, bsu ServiceURL) (container ContainerURL, name string) {
name = generateContainerName()
container = bsu.NewContainerURL(name)
return container, name
}
func getBlockBlobURL(c *chk.C, container azblob.ContainerURL) (blob azblob.BlockBlobURL, name string) {
func getBlockBlobURL(c *chk.C, container ContainerURL) (blob BlockBlobURL, name string) {
name = generateBlobName()
blob = container.NewBlockBlobURL(name)
return blob, name
}
func getAppendBlobURL(c *chk.C, container azblob.ContainerURL) (blob azblob.AppendBlobURL, name string) {
func getAppendBlobURL(c *chk.C, container ContainerURL) (blob AppendBlobURL, name string) {
name = generateBlobName()
blob = container.NewAppendBlobURL(name)
return blob, name
}
func getPageBlobURL(c *chk.C, container azblob.ContainerURL) (blob azblob.PageBlobURL, name string) {
func getPageBlobURL(c *chk.C, container ContainerURL) (blob PageBlobURL, name string) {
name = generateBlobName()
blob = container.NewPageBlobURL(name)
@ -143,33 +142,33 @@ func getRandomDataAndReader(n int) (*bytes.Reader, []byte) {
return bytes.NewReader(data), data
}
func createNewContainer(c *chk.C, bsu azblob.ServiceURL) (container azblob.ContainerURL, name string) {
func createNewContainer(c *chk.C, bsu ServiceURL) (container ContainerURL, name string) {
container, name = getContainerURL(c, bsu)
cResp, err := container.Create(ctx, nil, azblob.PublicAccessNone)
cResp, err := container.Create(ctx, nil, PublicAccessNone)
c.Assert(err, chk.IsNil)
c.Assert(cResp.StatusCode(), chk.Equals, 201)
return container, name
}
func createNewContainerWithSuffix(c *chk.C, bsu azblob.ServiceURL, suffix string) (container azblob.ContainerURL, name string) {
func createNewContainerWithSuffix(c *chk.C, bsu ServiceURL, suffix string) (container ContainerURL, name string) {
// The goal of adding the suffix is to be able to predetermine what order the containers will be in when listed.
// We still need the container prefix to come first, though, to ensure only containers as a part of this test
// are listed at all.
name = generateName(containerPrefix + suffix)
container = bsu.NewContainerURL(name)
cResp, err := container.Create(ctx, nil, azblob.PublicAccessNone)
cResp, err := container.Create(ctx, nil, PublicAccessNone)
c.Assert(err, chk.IsNil)
c.Assert(cResp.StatusCode(), chk.Equals, 201)
return container, name
}
func createNewBlockBlob(c *chk.C, container azblob.ContainerURL) (blob azblob.BlockBlobURL, name string) {
func createNewBlockBlob(c *chk.C, container ContainerURL) (blob BlockBlobURL, name string) {
blob, name = getBlockBlobURL(c, container)
cResp, err := blob.Upload(ctx, strings.NewReader(blockBlobDefaultData), azblob.BlobHTTPHeaders{},
nil, azblob.BlobAccessConditions{})
cResp, err := blob.Upload(ctx, strings.NewReader(blockBlobDefaultData), BlobHTTPHeaders{},
nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(cResp.StatusCode(), chk.Equals, 201)
@ -177,68 +176,68 @@ func createNewBlockBlob(c *chk.C, container azblob.ContainerURL) (blob azblob.Bl
return
}
func createNewAppendBlob(c *chk.C, container azblob.ContainerURL) (blob azblob.AppendBlobURL, name string) {
func createNewAppendBlob(c *chk.C, container ContainerURL) (blob AppendBlobURL, name string) {
blob, name = getAppendBlobURL(c, container)
resp, err := blob.Create(ctx, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
resp, err := blob.Create(ctx, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.StatusCode(), chk.Equals, 201)
return
}
func createNewPageBlob(c *chk.C, container azblob.ContainerURL) (blob azblob.PageBlobURL, name string) {
func createNewPageBlob(c *chk.C, container ContainerURL) (blob PageBlobURL, name string) {
blob, name = getPageBlobURL(c, container)
resp, err := blob.Create(ctx, azblob.PageBlobPageBytes*10, 0, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
resp, err := blob.Create(ctx, PageBlobPageBytes*10, 0, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.StatusCode(), chk.Equals, 201)
return
}
func createNewPageBlobWithSize(c *chk.C, container azblob.ContainerURL, sizeInBytes int64) (blob azblob.PageBlobURL, name string) {
func createNewPageBlobWithSize(c *chk.C, container ContainerURL, sizeInBytes int64) (blob PageBlobURL, name string) {
blob, name = getPageBlobURL(c, container)
resp, err := blob.Create(ctx, sizeInBytes, 0, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
resp, err := blob.Create(ctx, sizeInBytes, 0, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.StatusCode(), chk.Equals, 201)
return
}
func createBlockBlobWithPrefix(c *chk.C, container azblob.ContainerURL, prefix string) (blob azblob.BlockBlobURL, name string) {
func createBlockBlobWithPrefix(c *chk.C, container ContainerURL, prefix string) (blob BlockBlobURL, name string) {
name = prefix + generateName(blobPrefix)
blob = container.NewBlockBlobURL(name)
cResp, err := blob.Upload(ctx, strings.NewReader(blockBlobDefaultData), azblob.BlobHTTPHeaders{},
nil, azblob.BlobAccessConditions{})
cResp, err := blob.Upload(ctx, strings.NewReader(blockBlobDefaultData), BlobHTTPHeaders{},
nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(cResp.StatusCode(), chk.Equals, 201)
return
}
func deleteContainer(c *chk.C, container azblob.ContainerURL) {
resp, err := container.Delete(ctx, azblob.ContainerAccessConditions{})
func deleteContainer(c *chk.C, container ContainerURL) {
resp, err := container.Delete(ctx, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.StatusCode(), chk.Equals, 202)
}
func getGenericCredential(accountType string) (*azblob.SharedKeyCredential, error) {
func getGenericCredential(accountType string) (*SharedKeyCredential, error) {
accountNameEnvVar := accountType + "ACCOUNT_NAME"
accountKeyEnvVar := accountType + "ACCOUNT_KEY"
accountName, accountKey := os.Getenv(accountNameEnvVar), os.Getenv(accountKeyEnvVar)
if accountName == "" || accountKey == "" {
return nil, errors.New(accountNameEnvVar + " and/or " + accountKeyEnvVar + " environment variables not specified.")
}
return azblob.NewSharedKeyCredential(accountName, accountKey)
return NewSharedKeyCredential(accountName, accountKey)
}
//getOAuthCredential can intake a OAuth credential from environment variables in one of the following ways:
//Direct: Supply a ADAL OAuth token in OAUTH_TOKEN and application ID in APPLICATION_ID to refresh the supplied token.
//Client secret: Supply a client secret in CLIENT_SECRET and application ID in APPLICATION_ID for SPN auth.
//TENANT_ID is optional and will be inferred as common if it is not explicitly defined.
func getOAuthCredential(accountType string) (*azblob.TokenCredential, error) {
func getOAuthCredential(accountType string) (*TokenCredential, error) {
oauthTokenEnvVar := accountType + "OAUTH_TOKEN"
clientSecretEnvVar := accountType + "CLIENT_SECRET"
applicationIdEnvVar := accountType + "APPLICATION_ID"
@ -290,7 +289,7 @@ func getOAuthCredential(accountType string) (*azblob.TokenCredential, error) {
return nil, err
}
tc := azblob.NewTokenCredential(spt.Token().AccessToken, func(tc azblob.TokenCredential) time.Duration {
tc := NewTokenCredential(spt.Token().AccessToken, func(tc TokenCredential) time.Duration {
_ = spt.Refresh()
return time.Until(spt.Token().Expires())
})
@ -298,36 +297,36 @@ func getOAuthCredential(accountType string) (*azblob.TokenCredential, error) {
return &tc, nil
}
func getGenericBSU(accountType string) (azblob.ServiceURL, error) {
func getGenericBSU(accountType string) (ServiceURL, error) {
credential, err := getGenericCredential(accountType)
if err != nil {
return azblob.ServiceURL{}, err
return ServiceURL{}, err
}
pipeline := azblob.NewPipeline(credential, azblob.PipelineOptions{})
pipeline := NewPipeline(credential, PipelineOptions{})
blobPrimaryURL, _ := url.Parse("https://" + credential.AccountName() + ".blob.core.windows.net/")
return azblob.NewServiceURL(*blobPrimaryURL, pipeline), nil
return NewServiceURL(*blobPrimaryURL, pipeline), nil
}
func getBSU() azblob.ServiceURL {
func getBSU() ServiceURL {
bsu, _ := getGenericBSU("")
return bsu
}
func getAlternateBSU() (azblob.ServiceURL, error) {
func getAlternateBSU() (ServiceURL, error) {
return getGenericBSU("SECONDARY_")
}
func getPremiumBSU() (azblob.ServiceURL, error) {
func getPremiumBSU() (ServiceURL, error) {
return getGenericBSU("PREMIUM_")
}
func getBlobStorageBSU() (azblob.ServiceURL, error) {
func getBlobStorageBSU() (ServiceURL, error) {
return getGenericBSU("BLOB_STORAGE_")
}
func validateStorageError(c *chk.C, err error, code azblob.ServiceCodeType) {
serr, _ := err.(azblob.StorageError)
func validateStorageError(c *chk.C, err error, code ServiceCodeType) {
serr, _ := err.(StorageError)
c.Assert(serr.ServiceCode(), chk.Equals, code)
}
@ -348,10 +347,10 @@ func generateCurrentTimeWithModerateResolution() time.Time {
// those changes not being reflected yet, we will wait 30 seconds and try the test again. If it fails this time for any reason,
// we fail the test. It is the responsibility of the the testImplFunc to determine which error string indicates the test should be retried.
// There can only be one such string. All errors that cannot be due to this detail should be asserted and not returned as an error string.
func runTestRequiringServiceProperties(c *chk.C, bsu azblob.ServiceURL, code string,
enableServicePropertyFunc func(*chk.C, azblob.ServiceURL),
testImplFunc func(*chk.C, azblob.ServiceURL) error,
disableServicePropertyFunc func(*chk.C, azblob.ServiceURL)) {
func runTestRequiringServiceProperties(c *chk.C, bsu ServiceURL, code string,
enableServicePropertyFunc func(*chk.C, ServiceURL),
testImplFunc func(*chk.C, ServiceURL) error,
disableServicePropertyFunc func(*chk.C, ServiceURL)) {
enableServicePropertyFunc(c, bsu)
defer disableServicePropertyFunc(c, bsu)
err := testImplFunc(c, bsu)
@ -363,19 +362,19 @@ func runTestRequiringServiceProperties(c *chk.C, bsu azblob.ServiceURL, code str
}
}
func enableSoftDelete(c *chk.C, bsu azblob.ServiceURL) {
func enableSoftDelete(c *chk.C, bsu ServiceURL) {
days := int32(1)
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: true, Days: &days}})
c.Assert(err, chk.IsNil)
}
func disableSoftDelete(c *chk.C, bsu azblob.ServiceURL) {
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: false}})
func disableSoftDelete(c *chk.C, bsu ServiceURL) {
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: false}})
c.Assert(err, chk.IsNil)
}
func validateUpload(c *chk.C, blobURL azblob.BlockBlobURL) {
resp, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
func validateUpload(c *chk.C, blobURL BlockBlobURL) {
resp, err := blobURL.Download(ctx, 0, 0, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
data, _ := ioutil.ReadAll(resp.Response().Body)
c.Assert(data, chk.HasLen, 0)

Просмотреть файл

@ -1,4 +1,4 @@
package azblob_test
package azblob
import (
"context"
@ -10,7 +10,6 @@ import (
"bytes"
"strings"
"github.com/Azure/azure-storage-blob-go/azblob"
chk "gopkg.in/check.v1" // go get gopkg.in/check.v1
)
@ -21,23 +20,23 @@ func (s *aztestsSuite) TestAppendBlock(c *chk.C) {
blob := container.NewAppendBlobURL(generateBlobName())
resp, err := blob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
resp, err := blob.Create(context.Background(), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.StatusCode(), chk.Equals, 201)
appendResp, err := blob.AppendBlock(context.Background(), getReaderToRandomBytes(1024), azblob.AppendBlobAccessConditions{}, nil)
appendResp, err := blob.AppendBlock(context.Background(), getReaderToRandomBytes(1024), AppendBlobAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
c.Assert(appendResp.ContentMD5(), chk.Not(chk.Equals), "")
c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
c.Assert(appendResp.Version(), chk.Not(chk.Equals), "")
c.Assert(appendResp.Date().IsZero(), chk.Equals, false)
appendResp, err = blob.AppendBlock(context.Background(), getReaderToRandomBytes(1024), azblob.AppendBlobAccessConditions{}, nil)
appendResp, err = blob.AppendBlock(context.Background(), getReaderToRandomBytes(1024), AppendBlobAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "1024")
c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(2))
@ -50,19 +49,19 @@ func (s *aztestsSuite) TestAppendBlockWithMD5(c *chk.C) {
// set up blob to test
blob := container.NewAppendBlobURL(generateBlobName())
resp, err := blob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
resp, err := blob.Create(context.Background(), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.StatusCode(), chk.Equals, 201)
// test append block with valid MD5 value
readerToBody, body := getRandomDataAndReader(1024)
md5Value := md5.Sum(body)
appendResp, err := blob.AppendBlock(context.Background(), readerToBody, azblob.AppendBlobAccessConditions{}, md5Value[:])
appendResp, err := blob.AppendBlock(context.Background(), readerToBody, AppendBlobAccessConditions{}, md5Value[:])
c.Assert(err, chk.IsNil)
c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
c.Assert(appendResp.ContentMD5(), chk.DeepEquals, md5Value[:])
c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
@ -72,8 +71,8 @@ func (s *aztestsSuite) TestAppendBlockWithMD5(c *chk.C) {
// test append block with bad MD5 value
readerToBody, body = getRandomDataAndReader(1024)
_, badMD5 := getRandomDataAndReader(16)
appendResp, err = blob.AppendBlock(context.Background(), readerToBody, azblob.AppendBlobAccessConditions{}, badMD5[:])
validateStorageError(c, err, azblob.ServiceCodeMd5Mismatch)
appendResp, err = blob.AppendBlock(context.Background(), readerToBody, AppendBlobAccessConditions{}, badMD5[:])
validateStorageError(c, err, ServiceCodeMd5Mismatch)
}
func (s *aztestsSuite) TestAppendBlockFromURL(c *chk.C) {
@ -92,15 +91,15 @@ func (s *aztestsSuite) TestAppendBlockFromURL(c *chk.C) {
destBlob := container.NewAppendBlobURL(generateName("appenddest"))
// Prepare source blob for copy.
cResp1, err := srcBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
cResp1, err := srcBlob.Create(context.Background(), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(cResp1.StatusCode(), chk.Equals, 201)
appendResp, err := srcBlob.AppendBlock(context.Background(), r, azblob.AppendBlobAccessConditions{}, nil)
appendResp, err := srcBlob.AppendBlock(context.Background(), r, AppendBlobAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
c.Assert(appendResp.ContentMD5(), chk.Not(chk.Equals), "")
c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
@ -108,14 +107,14 @@ func (s *aztestsSuite) TestAppendBlockFromURL(c *chk.C) {
c.Assert(appendResp.Date().IsZero(), chk.Equals, false)
// Get source blob URL with SAS for AppendBlockFromURL.
srcBlobParts := azblob.NewBlobURLParts(srcBlob.URL())
srcBlobParts := NewBlobURLParts(srcBlob.URL())
srcBlobParts.SAS, err = azblob.BlobSASSignatureValues{
Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
srcBlobParts.SAS, err = BlobSASSignatureValues{
Protocol: SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
ContainerName: srcBlobParts.ContainerName,
BlobName: srcBlobParts.BlobName,
Permissions: azblob.BlobSASPermissions{Read: true}.String(),
Permissions: BlobSASPermissions{Read: true}.String(),
}.NewSASQueryParameters(credential)
if err != nil {
c.Fatal(err)
@ -124,15 +123,15 @@ func (s *aztestsSuite) TestAppendBlockFromURL(c *chk.C) {
srcBlobURLWithSAS := srcBlobParts.URL()
// Append block from URL.
cResp2, err := destBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
cResp2, err := destBlob.Create(context.Background(), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(cResp2.StatusCode(), chk.Equals, 201)
appendFromURLResp, err := destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), azblob.AppendBlobAccessConditions{}, azblob.ModifiedAccessConditions{}, nil)
appendFromURLResp, err := destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), AppendBlobAccessConditions{}, ModifiedAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
c.Assert(appendFromURLResp.Response().StatusCode, chk.Equals, 201)
c.Assert(appendFromURLResp.BlobAppendOffset(), chk.Equals, "0")
c.Assert(appendFromURLResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
c.Assert(appendFromURLResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(appendFromURLResp.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(appendFromURLResp.LastModified().IsZero(), chk.Equals, false)
c.Assert(appendFromURLResp.ContentMD5(), chk.Not(chk.Equals), "")
c.Assert(appendFromURLResp.RequestID(), chk.Not(chk.Equals), "")
@ -140,9 +139,9 @@ func (s *aztestsSuite) TestAppendBlockFromURL(c *chk.C) {
c.Assert(appendFromURLResp.Date().IsZero(), chk.Equals, false)
// Check data integrity through downloading.
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, CountToEnd, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
destData, err := ioutil.ReadAll(downloadResp.Body(azblob.RetryReaderOptions{}))
destData, err := ioutil.ReadAll(downloadResp.Body(RetryReaderOptions{}))
c.Assert(err, chk.IsNil)
c.Assert(destData, chk.DeepEquals, sourceData)
}
@ -164,15 +163,15 @@ func (s *aztestsSuite) TestAppendBlockFromURLWithMD5(c *chk.C) {
destBlob := container.NewAppendBlobURL(generateName("appenddest"))
// Prepare source blob for copy.
cResp1, err := srcBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
cResp1, err := srcBlob.Create(context.Background(), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(cResp1.StatusCode(), chk.Equals, 201)
appendResp, err := srcBlob.AppendBlock(context.Background(), r, azblob.AppendBlobAccessConditions{}, nil)
appendResp, err := srcBlob.AppendBlock(context.Background(), r, AppendBlobAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(appendResp.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
c.Assert(appendResp.ContentMD5(), chk.Not(chk.Equals), "")
c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
@ -180,14 +179,14 @@ func (s *aztestsSuite) TestAppendBlockFromURLWithMD5(c *chk.C) {
c.Assert(appendResp.Date().IsZero(), chk.Equals, false)
// Get source blob URL with SAS for AppendBlockFromURL.
srcBlobParts := azblob.NewBlobURLParts(srcBlob.URL())
srcBlobParts := NewBlobURLParts(srcBlob.URL())
srcBlobParts.SAS, err = azblob.BlobSASSignatureValues{
Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
srcBlobParts.SAS, err = BlobSASSignatureValues{
Protocol: SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
ContainerName: srcBlobParts.ContainerName,
BlobName: srcBlobParts.BlobName,
Permissions: azblob.BlobSASPermissions{Read: true}.String(),
Permissions: BlobSASPermissions{Read: true}.String(),
}.NewSASQueryParameters(credential)
if err != nil {
c.Fatal(err)
@ -196,15 +195,15 @@ func (s *aztestsSuite) TestAppendBlockFromURLWithMD5(c *chk.C) {
srcBlobURLWithSAS := srcBlobParts.URL()
// Append block from URL.
cResp2, err := destBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
cResp2, err := destBlob.Create(context.Background(), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(cResp2.StatusCode(), chk.Equals, 201)
appendFromURLResp, err := destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), azblob.AppendBlobAccessConditions{}, azblob.ModifiedAccessConditions{}, md5Value[:])
appendFromURLResp, err := destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), AppendBlobAccessConditions{}, ModifiedAccessConditions{}, md5Value[:])
c.Assert(err, chk.IsNil)
c.Assert(appendFromURLResp.Response().StatusCode, chk.Equals, 201)
c.Assert(appendFromURLResp.BlobAppendOffset(), chk.Equals, "0")
c.Assert(appendFromURLResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
c.Assert(appendFromURLResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(appendFromURLResp.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(appendFromURLResp.LastModified().IsZero(), chk.Equals, false)
c.Assert(appendFromURLResp.ContentMD5(), chk.DeepEquals, md5Value[:])
c.Assert(appendFromURLResp.RequestID(), chk.Not(chk.Equals), "")
@ -212,16 +211,16 @@ func (s *aztestsSuite) TestAppendBlockFromURLWithMD5(c *chk.C) {
c.Assert(appendFromURLResp.Date().IsZero(), chk.Equals, false)
// Check data integrity through downloading.
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, CountToEnd, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
destData, err := ioutil.ReadAll(downloadResp.Body(azblob.RetryReaderOptions{}))
destData, err := ioutil.ReadAll(downloadResp.Body(RetryReaderOptions{}))
c.Assert(err, chk.IsNil)
c.Assert(destData, chk.DeepEquals, sourceData)
// Test append block from URL with bad MD5 value
_, badMD5 := getRandomDataAndReader(16)
_, err = destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), azblob.AppendBlobAccessConditions{}, azblob.ModifiedAccessConditions{}, badMD5)
validateStorageError(c, err, azblob.ServiceCodeMd5Mismatch)
_, err = destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), AppendBlobAccessConditions{}, ModifiedAccessConditions{}, badMD5)
validateStorageError(c, err, ServiceCodeMd5Mismatch)
}
func (s *aztestsSuite) TestBlobCreateAppendMetadataNonEmpty(c *chk.C) {
@ -230,10 +229,10 @@ func (s *aztestsSuite) TestBlobCreateAppendMetadataNonEmpty(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getAppendBlobURL(c, containerURL)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata, azblob.BlobAccessConditions{})
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
}
@ -244,10 +243,10 @@ func (s *aztestsSuite) TestBlobCreateAppendMetadataEmpty(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getAppendBlobURL(c, containerURL)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.HasLen, 0)
}
@ -258,7 +257,7 @@ func (s *aztestsSuite) TestBlobCreateAppendMetadataInvalid(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getAppendBlobURL(c, containerURL)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, azblob.Metadata{"In valid!": "bar"}, azblob.BlobAccessConditions{})
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, Metadata{"In valid!": "bar"}, BlobAccessConditions{})
c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
}
@ -268,17 +267,17 @@ func (s *aztestsSuite) TestBlobCreateAppendHTTPHeaders(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getAppendBlobURL(c, containerURL)
_, err := blobURL.Create(ctx, basicHeaders, nil, azblob.BlobAccessConditions{})
_, err := blobURL.Create(ctx, basicHeaders, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
h := resp.NewHTTPHeaders()
c.Assert(h, chk.DeepEquals, basicHeaders)
}
func validateAppendBlobPut(c *chk.C, blobURL azblob.AppendBlobURL) {
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
func validateAppendBlobPut(c *chk.C, blobURL AppendBlobURL) {
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
}
@ -291,8 +290,8 @@ func (s *aztestsSuite) TestBlobCreateAppendIfModifiedSinceTrue(c *chk.C) {
currentTime := getRelativeTimeGMT(-10)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateAppendBlobPut(c, blobURL)
@ -306,9 +305,9 @@ func (s *aztestsSuite) TestBlobCreateAppendIfModifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobCreateAppendIfUnmodifiedSinceTrue(c *chk.C) {
@ -319,8 +318,8 @@ func (s *aztestsSuite) TestBlobCreateAppendIfUnmodifiedSinceTrue(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateAppendBlobPut(c, blobURL)
@ -334,9 +333,9 @@ func (s *aztestsSuite) TestBlobCreateAppendIfUnmodifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(-10)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobCreateAppendIfMatchTrue(c *chk.C) {
@ -345,10 +344,10 @@ func (s *aztestsSuite) TestBlobCreateAppendIfMatchTrue(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{})
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}})
c.Assert(err, chk.IsNil)
validateAppendBlobPut(c, blobURL)
@ -360,9 +359,9 @@ func (s *aztestsSuite) TestBlobCreateAppendIfMatchFalse(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobCreateAppendIfNoneMatchTrue(c *chk.C) {
@ -371,8 +370,8 @@ func (s *aztestsSuite) TestBlobCreateAppendIfNoneMatchTrue(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}})
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}})
c.Assert(err, chk.IsNil)
validateAppendBlobPut(c, blobURL)
@ -384,11 +383,11 @@ func (s *aztestsSuite) TestBlobCreateAppendIfNoneMatchFalse(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{})
_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := blobURL.Create(ctx, BlobHTTPHeaders{}, basicMetadata,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobAppendBlockNilBody(c *chk.C) {
@ -397,9 +396,9 @@ func (s *aztestsSuite) TestBlobAppendBlockNilBody(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, bytes.NewReader(nil), azblob.AppendBlobAccessConditions{}, nil)
_, err := blobURL.AppendBlock(ctx, bytes.NewReader(nil), AppendBlobAccessConditions{}, nil)
c.Assert(err, chk.NotNil)
validateStorageError(c, err, azblob.ServiceCodeInvalidHeaderValue)
validateStorageError(c, err, ServiceCodeInvalidHeaderValue)
}
func (s *aztestsSuite) TestBlobAppendBlockEmptyBody(c *chk.C) {
@ -408,8 +407,8 @@ func (s *aztestsSuite) TestBlobAppendBlockEmptyBody(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(""), azblob.AppendBlobAccessConditions{}, nil)
validateStorageError(c, err, azblob.ServiceCodeInvalidHeaderValue)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(""), AppendBlobAccessConditions{}, nil)
validateStorageError(c, err, ServiceCodeInvalidHeaderValue)
}
func (s *aztestsSuite) TestBlobAppendBlockNonExistantBlob(c *chk.C) {
@ -418,12 +417,12 @@ func (s *aztestsSuite) TestBlobAppendBlockNonExistantBlob(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getAppendBlobURL(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil)
validateStorageError(c, err, azblob.ServiceCodeBlobNotFound)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), AppendBlobAccessConditions{}, nil)
validateStorageError(c, err, ServiceCodeBlobNotFound)
}
func validateBlockAppended(c *chk.C, blobURL azblob.AppendBlobURL, expectedSize int) {
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
func validateBlockAppended(c *chk.C, blobURL AppendBlobURL, expectedSize int) {
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.ContentLength(), chk.Equals, int64(expectedSize))
}
@ -437,7 +436,7 @@ func (s *aztestsSuite) TestBlobAppendBlockIfModifiedSinceTrue(c *chk.C) {
currentTime := getRelativeTimeGMT(-10)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil)
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
@ -451,8 +450,8 @@ func (s *aztestsSuite) TestBlobAppendBlockIfModifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil)
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobAppendBlockIfUnmodifiedSinceTrue(c *chk.C) {
@ -463,7 +462,7 @@ func (s *aztestsSuite) TestBlobAppendBlockIfUnmodifiedSinceTrue(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil)
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
@ -477,8 +476,8 @@ func (s *aztestsSuite) TestBlobAppendBlockIfUnmodifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(-10)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil)
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobAppendBlockIfMatchTrue(c *chk.C) {
@ -487,10 +486,10 @@ func (s *aztestsSuite) TestBlobAppendBlockIfMatchTrue(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{})
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}}, nil)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}}, nil)
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
@ -503,8 +502,8 @@ func (s *aztestsSuite) TestBlobAppendBlockIfMatchFalse(c *chk.C) {
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}}, nil)
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}}, nil)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobAppendBlockIfNoneMatchTrue(c *chk.C) {
@ -514,7 +513,7 @@ func (s *aztestsSuite) TestBlobAppendBlockIfNoneMatchTrue(c *chk.C) {
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}}, nil)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}}, nil)
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
@ -526,11 +525,11 @@ func (s *aztestsSuite) TestBlobAppendBlockIfNoneMatchFalse(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{})
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}, nil)
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
AppendBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}, nil)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchTrueNegOne(c *chk.C) {
@ -540,7 +539,7 @@ func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchTrueNegOne(c *chk
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: -1}}, nil) // This will cause the library to set the value of the header to 0
AppendBlobAccessConditions{AppendPositionAccessConditions: AppendPositionAccessConditions{IfAppendPositionEqual: -1}}, nil) // This will cause the library to set the value of the header to 0
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
@ -552,10 +551,10 @@ func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchZero(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil) // The position will not match, but the condition should be ignored
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), AppendBlobAccessConditions{}, nil) // The position will not match, but the condition should be ignored
c.Assert(err, chk.IsNil)
_, err = blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: 0}}, nil)
AppendBlobAccessConditions{AppendPositionAccessConditions: AppendPositionAccessConditions{IfAppendPositionEqual: 0}}, nil)
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, 2*len(blockBlobDefaultData))
@ -567,10 +566,10 @@ func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchTrueNonZero(c *ch
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), AppendBlobAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: int64(len(blockBlobDefaultData))}}, nil)
AppendBlobAccessConditions{AppendPositionAccessConditions: AppendPositionAccessConditions{IfAppendPositionEqual: int64(len(blockBlobDefaultData))}}, nil)
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, len(blockBlobDefaultData)*2)
@ -582,11 +581,11 @@ func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchFalseNegOne(c *ch
defer deleteContainer(c, containerURL)
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), AppendBlobAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: -1}}, nil) // This will cause the library to set the value of the header to 0
validateStorageError(c, err, azblob.ServiceCodeAppendPositionConditionNotMet)
AppendBlobAccessConditions{AppendPositionAccessConditions: AppendPositionAccessConditions{IfAppendPositionEqual: -1}}, nil) // This will cause the library to set the value of the header to 0
validateStorageError(c, err, ServiceCodeAppendPositionConditionNotMet)
}
func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchFalseNonZero(c *chk.C) {
@ -596,8 +595,8 @@ func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchFalseNonZero(c *c
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: 12}}, nil)
validateStorageError(c, err, azblob.ServiceCodeAppendPositionConditionNotMet)
AppendBlobAccessConditions{AppendPositionAccessConditions: AppendPositionAccessConditions{IfAppendPositionEqual: 12}}, nil)
validateStorageError(c, err, ServiceCodeAppendPositionConditionNotMet)
}
func (s *aztestsSuite) TestBlobAppendBlockIfMaxSizeTrue(c *chk.C) {
@ -607,7 +606,7 @@ func (s *aztestsSuite) TestBlobAppendBlockIfMaxSizeTrue(c *chk.C) {
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfMaxSizeLessThanOrEqual: int64(len(blockBlobDefaultData) + 1)}}, nil)
AppendBlobAccessConditions{AppendPositionAccessConditions: AppendPositionAccessConditions{IfMaxSizeLessThanOrEqual: int64(len(blockBlobDefaultData) + 1)}}, nil)
c.Assert(err, chk.IsNil)
validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
@ -620,6 +619,6 @@ func (s *aztestsSuite) TestBlobAppendBlockIfMaxSizeFalse(c *chk.C) {
blobURL, _ := createNewAppendBlob(c, containerURL)
_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfMaxSizeLessThanOrEqual: int64(len(blockBlobDefaultData) - 1)}}, nil)
validateStorageError(c, err, azblob.ServiceCodeMaxBlobSizeConditionNotMet)
AppendBlobAccessConditions{AppendPositionAccessConditions: AppendPositionAccessConditions{IfMaxSizeLessThanOrEqual: int64(len(blockBlobDefaultData) - 1)}}, nil)
validateStorageError(c, err, ServiceCodeMaxBlobSizeConditionNotMet)
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,10 +1,12 @@
package azblob_test
package azblob
import (
"context"
"encoding/base64"
"encoding/binary"
"fmt"
"io/ioutil"
"math"
"time"
"crypto/md5"
@ -12,7 +14,7 @@ import (
"bytes"
"strings"
"github.com/Azure/azure-storage-blob-go/azblob"
guuid "github.com/google/uuid"
chk "gopkg.in/check.v1" // go get gopkg.in/check.v1
)
@ -25,7 +27,7 @@ func (s *aztestsSuite) TestStageGetBlocks(c *chk.C) {
blockID := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%6d", 0)))
putResp, err := blob.StageBlock(context.Background(), blockID, getReaderToRandomBytes(1024), azblob.LeaseAccessConditions{}, nil)
putResp, err := blob.StageBlock(context.Background(), blockID, getReaderToRandomBytes(1024), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
c.Assert(putResp.Response().StatusCode, chk.Equals, 201)
c.Assert(putResp.ContentMD5(), chk.Not(chk.Equals), "")
@ -33,11 +35,11 @@ func (s *aztestsSuite) TestStageGetBlocks(c *chk.C) {
c.Assert(putResp.Version(), chk.Not(chk.Equals), "")
c.Assert(putResp.Date().IsZero(), chk.Equals, false)
blockList, err := blob.GetBlockList(context.Background(), azblob.BlockListAll, azblob.LeaseAccessConditions{})
blockList, err := blob.GetBlockList(context.Background(), BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(blockList.Response().StatusCode, chk.Equals, 200)
c.Assert(blockList.LastModified().IsZero(), chk.Equals, true)
c.Assert(blockList.ETag(), chk.Equals, azblob.ETagNone)
c.Assert(blockList.ETag(), chk.Equals, ETagNone)
c.Assert(blockList.ContentType(), chk.Not(chk.Equals), "")
c.Assert(blockList.BlobContentLength(), chk.Equals, int64(-1))
c.Assert(blockList.RequestID(), chk.Not(chk.Equals), "")
@ -46,21 +48,21 @@ func (s *aztestsSuite) TestStageGetBlocks(c *chk.C) {
c.Assert(blockList.CommittedBlocks, chk.HasLen, 0)
c.Assert(blockList.UncommittedBlocks, chk.HasLen, 1)
listResp, err := blob.CommitBlockList(context.Background(), []string{blockID}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
listResp, err := blob.CommitBlockList(context.Background(), []string{blockID}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(listResp.Response().StatusCode, chk.Equals, 201)
c.Assert(listResp.LastModified().IsZero(), chk.Equals, false)
c.Assert(listResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(listResp.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(listResp.ContentMD5(), chk.Not(chk.Equals), "")
c.Assert(listResp.RequestID(), chk.Not(chk.Equals), "")
c.Assert(listResp.Version(), chk.Not(chk.Equals), "")
c.Assert(listResp.Date().IsZero(), chk.Equals, false)
blockList, err = blob.GetBlockList(context.Background(), azblob.BlockListAll, azblob.LeaseAccessConditions{})
blockList, err = blob.GetBlockList(context.Background(), BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(blockList.Response().StatusCode, chk.Equals, 200)
c.Assert(blockList.LastModified().IsZero(), chk.Equals, false)
c.Assert(blockList.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
c.Assert(blockList.ETag(), chk.Not(chk.Equals), ETagNone)
c.Assert(blockList.ContentType(), chk.Not(chk.Equals), "")
c.Assert(blockList.BlobContentLength(), chk.Equals, int64(1024))
c.Assert(blockList.RequestID(), chk.Not(chk.Equals), "")
@ -86,19 +88,19 @@ func (s *aztestsSuite) TestStageBlockFromURL(c *chk.C) {
destBlob := container.NewBlockBlobURL(generateBlobName())
// Prepare source blob for copy.
uploadSrcResp, err := srcBlob.Upload(ctx, r, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
uploadSrcResp, err := srcBlob.Upload(ctx, r, BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(uploadSrcResp.Response().StatusCode, chk.Equals, 201)
// Get source blob URL with SAS for StageFromURL.
srcBlobParts := azblob.NewBlobURLParts(srcBlob.URL())
srcBlobParts := NewBlobURLParts(srcBlob.URL())
srcBlobParts.SAS, err = azblob.BlobSASSignatureValues{
Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
srcBlobParts.SAS, err = BlobSASSignatureValues{
Protocol: SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
ContainerName: srcBlobParts.ContainerName,
BlobName: srcBlobParts.BlobName,
Permissions: azblob.BlobSASPermissions{Read: true}.String(),
Permissions: BlobSASPermissions{Read: true}.String(),
}.NewSASQueryParameters(credential)
if err != nil {
c.Fatal(err)
@ -108,7 +110,7 @@ func (s *aztestsSuite) TestStageBlockFromURL(c *chk.C) {
// Stage blocks from URL.
blockID1, blockID2 := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%6d", 0))), base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%6d", 1)))
stageResp1, err := destBlob.StageBlockFromURL(ctx, blockID1, srcBlobURLWithSAS, 0, 4*1024*1024, azblob.LeaseAccessConditions{}, azblob.ModifiedAccessConditions{})
stageResp1, err := destBlob.StageBlockFromURL(ctx, blockID1, srcBlobURLWithSAS, 0, 4*1024*1024, LeaseAccessConditions{}, ModifiedAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(stageResp1.Response().StatusCode, chk.Equals, 201)
c.Assert(stageResp1.ContentMD5(), chk.Not(chk.Equals), "")
@ -116,7 +118,7 @@ func (s *aztestsSuite) TestStageBlockFromURL(c *chk.C) {
c.Assert(stageResp1.Version(), chk.Not(chk.Equals), "")
c.Assert(stageResp1.Date().IsZero(), chk.Equals, false)
stageResp2, err := destBlob.StageBlockFromURL(ctx, blockID2, srcBlobURLWithSAS, 4*1024*1024, azblob.CountToEnd, azblob.LeaseAccessConditions{}, azblob.ModifiedAccessConditions{})
stageResp2, err := destBlob.StageBlockFromURL(ctx, blockID2, srcBlobURLWithSAS, 4*1024*1024, CountToEnd, LeaseAccessConditions{}, ModifiedAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(stageResp2.Response().StatusCode, chk.Equals, 201)
c.Assert(stageResp2.ContentMD5(), chk.Not(chk.Equals), "")
@ -125,21 +127,21 @@ func (s *aztestsSuite) TestStageBlockFromURL(c *chk.C) {
c.Assert(stageResp2.Date().IsZero(), chk.Equals, false)
// Check block list.
blockList, err := destBlob.GetBlockList(context.Background(), azblob.BlockListAll, azblob.LeaseAccessConditions{})
blockList, err := destBlob.GetBlockList(context.Background(), BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(blockList.Response().StatusCode, chk.Equals, 200)
c.Assert(blockList.CommittedBlocks, chk.HasLen, 0)
c.Assert(blockList.UncommittedBlocks, chk.HasLen, 2)
// Commit block list.
listResp, err := destBlob.CommitBlockList(context.Background(), []string{blockID1, blockID2}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
listResp, err := destBlob.CommitBlockList(context.Background(), []string{blockID1, blockID2}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(listResp.Response().StatusCode, chk.Equals, 201)
// Check data integrity through downloading.
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, CountToEnd, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
destData, err := ioutil.ReadAll(downloadResp.Body(azblob.RetryReaderOptions{}))
destData, err := ioutil.ReadAll(downloadResp.Body(RetryReaderOptions{}))
c.Assert(err, chk.IsNil)
c.Assert(destData, chk.DeepEquals, sourceData)
}
@ -161,19 +163,19 @@ func (s *aztestsSuite) TestCopyBlockBlobFromURL(c *chk.C) {
destBlob := container.NewBlockBlobURL(generateBlobName())
// Prepare source blob for copy.
uploadSrcResp, err := srcBlob.Upload(ctx, r, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
uploadSrcResp, err := srcBlob.Upload(ctx, r, BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(uploadSrcResp.Response().StatusCode, chk.Equals, 201)
// Get source blob URL with SAS for StageFromURL.
srcBlobParts := azblob.NewBlobURLParts(srcBlob.URL())
srcBlobParts := NewBlobURLParts(srcBlob.URL())
srcBlobParts.SAS, err = azblob.BlobSASSignatureValues{
Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
srcBlobParts.SAS, err = BlobSASSignatureValues{
Protocol: SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
ContainerName: srcBlobParts.ContainerName,
BlobName: srcBlobParts.BlobName,
Permissions: azblob.BlobSASPermissions{Read: true}.String(),
Permissions: BlobSASPermissions{Read: true}.String(),
}.NewSASQueryParameters(credential)
if err != nil {
c.Fatal(err)
@ -182,7 +184,7 @@ func (s *aztestsSuite) TestCopyBlockBlobFromURL(c *chk.C) {
srcBlobURLWithSAS := srcBlobParts.URL()
// Invoke copy blob from URL.
resp, err := destBlob.CopyFromURL(ctx, srcBlobURLWithSAS, azblob.Metadata{"foo": "bar"}, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{}, sourceDataMD5Value[:])
resp, err := destBlob.CopyFromURL(ctx, srcBlobURLWithSAS, Metadata{"foo": "bar"}, ModifiedAccessConditions{}, BlobAccessConditions{}, sourceDataMD5Value[:])
c.Assert(err, chk.IsNil)
c.Assert(resp.Response().StatusCode, chk.Equals, 202)
c.Assert(resp.ETag(), chk.Not(chk.Equals), "")
@ -194,9 +196,9 @@ func (s *aztestsSuite) TestCopyBlockBlobFromURL(c *chk.C) {
c.Assert(string(resp.CopyStatus()), chk.DeepEquals, "success")
// Check data integrity through downloading.
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
downloadResp, err := destBlob.BlobURL.Download(ctx, 0, CountToEnd, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
destData, err := ioutil.ReadAll(downloadResp.Body(azblob.RetryReaderOptions{}))
destData, err := ioutil.ReadAll(downloadResp.Body(RetryReaderOptions{}))
c.Assert(err, chk.IsNil)
c.Assert(destData, chk.DeepEquals, sourceData)
@ -205,11 +207,11 @@ func (s *aztestsSuite) TestCopyBlockBlobFromURL(c *chk.C) {
// Edge case 1: Provide bad MD5 and make sure the copy fails
_, badMD5 := getRandomDataAndReader(16)
_, err = destBlob.CopyFromURL(ctx, srcBlobURLWithSAS, azblob.Metadata{}, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{}, badMD5)
_, err = destBlob.CopyFromURL(ctx, srcBlobURLWithSAS, Metadata{}, ModifiedAccessConditions{}, BlobAccessConditions{}, badMD5)
c.Assert(err, chk.NotNil)
// Edge case 2: Not providing any source MD5 should see the CRC getting returned instead
resp, err = destBlob.CopyFromURL(ctx, srcBlobURLWithSAS, azblob.Metadata{}, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{}, nil)
resp, err = destBlob.CopyFromURL(ctx, srcBlobURLWithSAS, Metadata{}, ModifiedAccessConditions{}, BlobAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
c.Assert(resp.Response().StatusCode, chk.Equals, 202)
c.Assert(resp.XMsContentCrc64(), chk.Not(chk.Equals), "")
@ -229,12 +231,12 @@ func (s *aztestsSuite) TestBlobSASQueryParamOverrideResponseHeaders(c *chk.C) {
ctx := context.Background() // Use default Background context
blob := container.NewBlockBlobURL(generateBlobName())
uploadResp, err := blob.Upload(ctx, r, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
uploadResp, err := blob.Upload(ctx, r, BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(uploadResp.Response().StatusCode, chk.Equals, 201)
// Get blob URL with SAS.
blobParts := azblob.NewBlobURLParts(blob.URL())
blobParts := NewBlobURLParts(blob.URL())
cacheControlVal := "cache-control-override"
contentDispositionVal := "content-disposition-override"
@ -242,12 +244,12 @@ func (s *aztestsSuite) TestBlobSASQueryParamOverrideResponseHeaders(c *chk.C) {
contentLanguageVal := "content-language-override"
contentTypeVal := "content-type-override"
blobParts.SAS, err = azblob.BlobSASSignatureValues{
Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
blobParts.SAS, err = BlobSASSignatureValues{
Protocol: SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
ContainerName: blobParts.ContainerName,
BlobName: blobParts.BlobName,
Permissions: azblob.BlobSASPermissions{Read: true}.String(),
Permissions: BlobSASPermissions{Read: true}.String(),
CacheControl: cacheControlVal,
ContentDisposition: contentDispositionVal,
ContentEncoding: contentEncodingVal,
@ -258,9 +260,9 @@ func (s *aztestsSuite) TestBlobSASQueryParamOverrideResponseHeaders(c *chk.C) {
c.Fatal(err)
}
blobURL := azblob.NewBlobURL(blobParts.URL(), azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{}))
blobURL := NewBlobURL(blobParts.URL(), NewPipeline(NewAnonymousCredential(), PipelineOptions{}))
gResp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
gResp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(gResp.CacheControl(), chk.Equals, cacheControlVal)
c.Assert(gResp.ContentDisposition(), chk.Equals, contentDispositionVal)
@ -280,7 +282,7 @@ func (s *aztestsSuite) TestStageBlockWithMD5(c *chk.C) {
// test put block with valid MD5 value
readerToBody, body := getRandomDataAndReader(1024)
md5Value := md5.Sum(body)
putResp, err := blob.StageBlock(context.Background(), blockID, readerToBody, azblob.LeaseAccessConditions{}, md5Value[:])
putResp, err := blob.StageBlock(context.Background(), blockID, readerToBody, LeaseAccessConditions{}, md5Value[:])
c.Assert(err, chk.IsNil)
c.Assert(putResp.Response().StatusCode, chk.Equals, 201)
c.Assert(putResp.ContentMD5(), chk.DeepEquals, md5Value[:])
@ -291,8 +293,8 @@ func (s *aztestsSuite) TestStageBlockWithMD5(c *chk.C) {
// test put block with bad MD5 value
readerToBody, body = getRandomDataAndReader(1024)
_, badMD5 := getRandomDataAndReader(16)
putResp, err = blob.StageBlock(context.Background(), blockID, readerToBody, azblob.LeaseAccessConditions{}, badMD5[:])
validateStorageError(c, err, azblob.ServiceCodeMd5Mismatch)
putResp, err = blob.StageBlock(context.Background(), blockID, readerToBody, LeaseAccessConditions{}, badMD5[:])
validateStorageError(c, err, ServiceCodeMd5Mismatch)
}
func (s *aztestsSuite) TestBlobPutBlobNonEmptyBody(c *chk.C) {
@ -301,10 +303,10 @@ func (s *aztestsSuite) TestBlobPutBlobNonEmptyBody(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.Upload(ctx, strings.NewReader(blockBlobDefaultData), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err := blobURL.Upload(ctx, strings.NewReader(blockBlobDefaultData), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
resp, err := blobURL.Download(ctx, 0, 0, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
data, err := ioutil.ReadAll(resp.Response().Body)
c.Assert(string(data), chk.Equals, blockBlobDefaultData)
@ -316,10 +318,10 @@ func (s *aztestsSuite) TestBlobPutBlobHTTPHeaders(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), basicHeaders, nil, azblob.BlobAccessConditions{})
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), basicHeaders, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
h := resp.NewHTTPHeaders()
h.ContentMD5 = nil // the service generates a MD5 value, omit before comparing
@ -332,10 +334,10 @@ func (s *aztestsSuite) TestBlobPutBlobMetadataNotEmpty(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, basicMetadata, azblob.BlobAccessConditions{})
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
}
@ -346,10 +348,10 @@ func (s *aztestsSuite) TestBlobPutBlobMetadataEmpty(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.HasLen, 0)
}
@ -360,7 +362,7 @@ func (s *aztestsSuite) TestBlobPutBlobMetadataInvalid(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.Upload(ctx, nil, azblob.BlobHTTPHeaders{}, azblob.Metadata{"In valid!": "bar"}, azblob.BlobAccessConditions{})
_, err := blobURL.Upload(ctx, nil, BlobHTTPHeaders{}, Metadata{"In valid!": "bar"}, BlobAccessConditions{})
c.Assert(strings.Contains(err.Error(), validationErrorSubstring), chk.Equals, true)
}
@ -372,8 +374,8 @@ func (s *aztestsSuite) TestBlobPutBlobIfModifiedSinceTrue(c *chk.C) {
currentTime := getRelativeTimeGMT(-10)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateUpload(c, blobURL)
@ -387,9 +389,9 @@ func (s *aztestsSuite) TestBlobPutBlobIfModifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobPutBlobIfUnmodifiedSinceTrue(c *chk.C) {
@ -400,8 +402,8 @@ func (s *aztestsSuite) TestBlobPutBlobIfUnmodifiedSinceTrue(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateUpload(c, blobURL)
@ -415,9 +417,9 @@ func (s *aztestsSuite) TestBlobPutBlobIfUnmodifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(-10)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobPutBlobIfMatchTrue(c *chk.C) {
@ -426,11 +428,11 @@ func (s *aztestsSuite) TestBlobPutBlobIfMatchTrue(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewBlockBlob(c, containerURL)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}})
c.Assert(err, chk.IsNil)
validateUpload(c, blobURL)
@ -442,12 +444,12 @@ func (s *aztestsSuite) TestBlobPutBlobIfMatchFalse(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewBlockBlob(c, containerURL)
_, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
_, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobPutBlobIfNoneMatchTrue(c *chk.C) {
@ -456,11 +458,11 @@ func (s *aztestsSuite) TestBlobPutBlobIfNoneMatchTrue(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewBlockBlob(c, containerURL)
_, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
_, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}})
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}})
c.Assert(err, chk.IsNil)
validateUpload(c, blobURL)
@ -472,12 +474,20 @@ func (s *aztestsSuite) TestBlobPutBlobIfNoneMatchFalse(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := createNewBlockBlob(c, containerURL)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err = blobURL.Upload(ctx, bytes.NewReader(nil), BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
var blockID string // a single blockID used in tests when only a single ID is needed
func init() {
u := [64]byte{}
binary.BigEndian.PutUint32((u[len(guuid.UUID{}):]), math.MaxUint32)
blockID = base64.StdEncoding.EncodeToString(u[:])
}
func (s *aztestsSuite) TestBlobGetBlockListNone(c *chk.C) {
@ -486,10 +496,10 @@ func (s *aztestsSuite) TestBlobGetBlockListNone(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListNone, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListNone, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 0)
c.Assert(resp.UncommittedBlocks, chk.HasLen, 0) // Not specifying a block list type should default to only returning committed blocks
@ -501,10 +511,10 @@ func (s *aztestsSuite) TestBlobGetBlockListUncommitted(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListUncommitted, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListUncommitted, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 0)
c.Assert(resp.UncommittedBlocks, chk.HasLen, 1)
@ -516,12 +526,12 @@ func (s *aztestsSuite) TestBlobGetBlockListCommitted(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{azblob.BlockID{0}.ToBase64()}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err = blobURL.CommitBlockList(ctx, []string{blockID}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListCommitted, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListCommitted, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 1)
c.Assert(resp.UncommittedBlocks, chk.HasLen, 0)
@ -533,10 +543,10 @@ func (s *aztestsSuite) TestBlobGetBlockListCommittedEmpty(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListCommitted, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListCommitted, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 0)
c.Assert(resp.UncommittedBlocks, chk.HasLen, 0)
@ -548,8 +558,8 @@ func (s *aztestsSuite) TestBlobGetBlockListBothEmpty(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeBlobNotFound)
_, err := blobURL.GetBlockList(ctx, BlockListAll, LeaseAccessConditions{})
validateStorageError(c, err, ServiceCodeBlobNotFound)
}
func (s *aztestsSuite) TestBlobGetBlockListBothNotEmpty(c *chk.C) {
@ -558,26 +568,28 @@ func (s *aztestsSuite) TestBlobGetBlockListBothNotEmpty(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
id := newID()
// Put and commit two blocks
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, id.next(), strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.StageBlock(ctx, azblob.BlockID{1}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err = blobURL.StageBlock(ctx, id.next(), strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{azblob.BlockID{1}.ToBase64(), azblob.BlockID{0}.ToBase64()}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err = blobURL.CommitBlockList(ctx, id.issued(), BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
// Put two uncommitted blocks
_, err = blobURL.StageBlock(ctx, azblob.BlockID{3}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err = blobURL.StageBlock(ctx, id.next(), strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.StageBlock(ctx, azblob.BlockID{2}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err = blobURL.StageBlock(ctx, id.next(), strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks[0].Name, chk.Equals, azblob.BlockID{1}.ToBase64())
c.Assert(resp.CommittedBlocks[1].Name, chk.Equals, azblob.BlockID{0}.ToBase64()) // Committed blocks are returned in the order they are committed (in the commit list)
c.Assert(resp.UncommittedBlocks[0].Name, chk.Equals, azblob.BlockID{2}.ToBase64()) // Uncommitted blocks are returned in alphabetical order
c.Assert(resp.UncommittedBlocks[1].Name, chk.Equals, azblob.BlockID{3}.ToBase64())
c.Assert(resp.CommittedBlocks[0].Name, chk.Equals, id.issued()[0])
c.Assert(resp.CommittedBlocks[1].Name, chk.Equals, id.issued()[1]) // Committed blocks are returned in the order they are committed (in the commit list)
c.Assert(resp.UncommittedBlocks[0].Name, chk.Equals, id.issued()[2]) // Uncommitted blocks are returned in alphabetical order
c.Assert(resp.UncommittedBlocks[1].Name, chk.Equals, id.issued()[3])
}
func (s *aztestsSuite) TestBlobGetBlockListInvalidType(c *chk.C) {
@ -586,11 +598,11 @@ func (s *aztestsSuite) TestBlobGetBlockListInvalidType(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.GetBlockList(ctx, azblob.BlockListType("garbage"), azblob.LeaseAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeInvalidQueryParameterValue)
_, err = blobURL.GetBlockList(ctx, BlockListType("garbage"), LeaseAccessConditions{})
validateStorageError(c, err, ServiceCodeInvalidQueryParameterValue)
}
func (s *aztestsSuite) TestBlobGetBlockListSnapshot(c *chk.C) {
@ -599,16 +611,16 @@ func (s *aztestsSuite) TestBlobGetBlockListSnapshot(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{azblob.BlockID{0}.ToBase64()}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err = blobURL.CommitBlockList(ctx, []string{blockID}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
resp, err := blobURL.CreateSnapshot(ctx, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
snapshotURL := blobURL.WithSnapshot(resp.Snapshot())
resp2, err := snapshotURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
resp2, err := snapshotURL.GetBlockList(ctx, BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp2.CommittedBlocks, chk.HasLen, 1)
}
@ -619,8 +631,8 @@ func (s *aztestsSuite) TestBlobPutBlockIDInvalidCharacters(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, "!!", strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
validateStorageError(c, err, azblob.ServiceCodeInvalidQueryParameterValue)
_, err := blobURL.StageBlock(ctx, "!!", strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
validateStorageError(c, err, ServiceCodeInvalidQueryParameterValue)
}
func (s *aztestsSuite) TestBlobPutBlockIDInvalidLength(c *chk.C) {
@ -629,10 +641,10 @@ func (s *aztestsSuite) TestBlobPutBlockIDInvalidLength(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.StageBlock(ctx, "00000000", strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
validateStorageError(c, err, azblob.ServiceCodeInvalidBlobOrBlock)
_, err = blobURL.StageBlock(ctx, "00000000", strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
validateStorageError(c, err, ServiceCodeInvalidBlobOrBlock)
}
func (s *aztestsSuite) TestBlobPutBlockEmptyBody(c *chk.C) {
@ -641,36 +653,36 @@ func (s *aztestsSuite) TestBlobPutBlockEmptyBody(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, _ := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(""), azblob.LeaseAccessConditions{}, nil)
validateStorageError(c, err, azblob.ServiceCodeInvalidHeaderValue)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(""), LeaseAccessConditions{}, nil)
validateStorageError(c, err, ServiceCodeInvalidHeaderValue)
}
func setupPutBlockListTest(c *chk.C) (containerURL azblob.ContainerURL, blobURL azblob.BlockBlobURL, id string) {
func setupPutBlockListTest(c *chk.C) (containerURL ContainerURL, blobURL BlockBlobURL, id string) {
bsu := getBSU()
containerURL, _ = createNewContainer(c, bsu)
blobURL, _ = getBlockBlobURL(c, containerURL)
id = azblob.BlockID{0}.ToBase64()
_, err := blobURL.StageBlock(ctx, id, strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
return
return containerURL, blobURL, blockID
}
func (s *aztestsSuite) TestBlobPutBlockListInvalidID(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id[:2]}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeInvalidBlockID)
_, err := blobURL.CommitBlockList(ctx, []string{id[:2]}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
validateStorageError(c, err, ServiceCodeInvalidBlockID)
}
func (s *aztestsSuite) TestBlobPutBlockListDuplicateBlocks(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id, id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{id, id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 2)
}
@ -679,10 +691,10 @@ func (s *aztestsSuite) TestBlobPutBlockListEmptyList(c *chk.C) {
containerURL, blobURL, _ := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{}, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{}, BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 0)
}
@ -691,10 +703,10 @@ func (s *aztestsSuite) TestBlobPutBlockListMetadataEmpty(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.HasLen, 0)
}
@ -703,10 +715,10 @@ func (s *aztestsSuite) TestBlobPutBlockListMetadataNonEmpty(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, basicMetadata, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
}
@ -715,10 +727,10 @@ func (s *aztestsSuite) TestBlobPutBlockListHTTPHeaders(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, basicHeaders, nil, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{id}, basicHeaders, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{})
h := resp.NewHTTPHeaders()
c.Assert(h, chk.DeepEquals, basicHeaders)
}
@ -727,19 +739,19 @@ func (s *aztestsSuite) TestBlobPutBlockListHTTPHeadersEmpty(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"}, nil, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{ContentDisposition: "my_disposition"}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err = blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.ContentDisposition(), chk.Equals, "")
}
func validateBlobCommitted(c *chk.C, blobURL azblob.BlockBlobURL) {
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
func validateBlobCommitted(c *chk.C, blobURL BlockBlobURL) {
resp, err := blobURL.GetBlockList(ctx, BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 1)
}
@ -747,13 +759,13 @@ func validateBlobCommitted(c *chk.C, blobURL azblob.BlockBlobURL) {
func (s *aztestsSuite) TestBlobPutBlockListIfModifiedSinceTrue(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{}) // The blob must actually exist to have a modifed time
c.Assert(err, chk.IsNil)
currentTime := getRelativeTimeGMT(-10)
_, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
_, err = blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateBlobCommitted(c, blobURL)
@ -765,21 +777,21 @@ func (s *aztestsSuite) TestBlobPutBlockListIfModifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobPutBlockListIfUnmodifiedSinceTrue(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{}) // The blob must actually exist to have a modifed time
c.Assert(err, chk.IsNil)
currentTime := getRelativeTimeGMT(10)
_, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
_, err = blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateBlobCommitted(c, blobURL)
@ -787,25 +799,25 @@ func (s *aztestsSuite) TestBlobPutBlockListIfUnmodifiedSinceTrue(c *chk.C) {
func (s *aztestsSuite) TestBlobPutBlockListIfUnmodifiedSinceFalse(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time
blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{}) // The blob must actually exist to have a modifed time
defer deleteContainer(c, containerURL)
currentTime := getRelativeTimeGMT(-10)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobPutBlockListIfMatchTrue(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
resp, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time
resp, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{}) // The blob must actually exist to have a modifed time
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
_, err = blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}})
c.Assert(err, chk.IsNil)
validateBlobCommitted(c, blobURL)
@ -814,23 +826,23 @@ func (s *aztestsSuite) TestBlobPutBlockListIfMatchTrue(c *chk.C) {
func (s *aztestsSuite) TestBlobPutBlockListIfMatchFalse(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{}) // The blob must actually exist to have a modifed time
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}})
_, err = blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobPutBlockListIfNoneMatchTrue(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{}) // The blob must actually exist to have a modifed time
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}})
_, err = blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}})
c.Assert(err, chk.IsNil)
validateBlobCommitted(c, blobURL)
@ -839,22 +851,22 @@ func (s *aztestsSuite) TestBlobPutBlockListIfNoneMatchTrue(c *chk.C) {
func (s *aztestsSuite) TestBlobPutBlockListIfNoneMatchFalse(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
resp, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time
resp, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{}) // The blob must actually exist to have a modifed time
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil,
azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
_, err = blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil,
BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestBlobPutBlockListValidateData(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
resp, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
resp, err := blobURL.Download(ctx, 0, 0, BlobAccessConditions{}, false)
c.Assert(err, chk.IsNil)
data, _ := ioutil.ReadAll(resp.Response().Body)
c.Assert(string(data), chk.Equals, blockBlobDefaultData)
@ -864,22 +876,22 @@ func (s *aztestsSuite) TestBlobPutBlockListModifyBlob(c *chk.C) {
containerURL, blobURL, id := setupPutBlockListTest(c)
defer deleteContainer(c, containerURL)
_, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err := blobURL.CommitBlockList(ctx, []string{id}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
_, err = blobURL.StageBlock(ctx, "0001", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil)
_, err = blobURL.StageBlock(ctx, "0001", bytes.NewReader([]byte("new data")), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.StageBlock(ctx, "0010", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil)
_, err = blobURL.StageBlock(ctx, "0010", bytes.NewReader([]byte("new data")), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.StageBlock(ctx, "0011", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil)
_, err = blobURL.StageBlock(ctx, "0011", bytes.NewReader([]byte("new data")), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.StageBlock(ctx, "0100", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil)
_, err = blobURL.StageBlock(ctx, "0100", bytes.NewReader([]byte("new data")), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
_, err = blobURL.CommitBlockList(ctx, []string{"0001", "0011"}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
_, err = blobURL.CommitBlockList(ctx, []string{"0001", "0011"}, BlobHTTPHeaders{}, nil, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
resp, err := blobURL.GetBlockList(ctx, BlockListAll, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.CommittedBlocks, chk.HasLen, 2)
c.Assert(resp.CommittedBlocks[0].Name, chk.Equals, "0001")

Просмотреть файл

@ -1,22 +1,19 @@
package azblob_test
package azblob
import (
"context"
"time"
"bytes"
"context"
"errors"
"os"
"strconv"
"strings"
"time"
"github.com/Azure/azure-storage-blob-go/azblob"
chk "gopkg.in/check.v1" // go get gopkg.in/check.v1
)
func delContainer(c *chk.C, container azblob.ContainerURL) {
resp, err := container.Delete(context.Background(), azblob.ContainerAccessConditions{})
func delContainer(c *chk.C, container ContainerURL) {
resp, err := container.Delete(context.Background(), ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.Response().StatusCode, chk.Equals, 202)
}
@ -32,7 +29,7 @@ func (s *aztestsSuite) TestNewContainerURLValidName(c *chk.C) {
func (s *aztestsSuite) TestCreateRootContainerURL(c *chk.C) {
bsu := getBSU()
testURL := bsu.NewContainerURL(azblob.ContainerNameRoot)
testURL := bsu.NewContainerURL(ContainerNameRoot)
correctURL := "https://" + os.Getenv("ACCOUNT_NAME") + ".blob.core.windows.net/$root"
temp := testURL.URL()
@ -44,7 +41,7 @@ func (s *aztestsSuite) TestAccountWithPipeline(c *chk.C) {
bsu = bsu.WithPipeline(testPipeline{}) // testPipeline returns an identifying message as an error
containerURL := bsu.NewContainerURL("name")
_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob)
c.Assert(err.Error(), chk.Equals, testPipelineMessage)
}
@ -53,18 +50,18 @@ func (s *aztestsSuite) TestContainerCreateInvalidName(c *chk.C) {
bsu := getBSU()
containerURL := bsu.NewContainerURL("foo bar")
_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob)
validateStorageError(c, err, azblob.ServiceCodeInvalidResourceName)
validateStorageError(c, err, ServiceCodeInvalidResourceName)
}
func (s *aztestsSuite) TestContainerCreateEmptyName(c *chk.C) {
bsu := getBSU()
containerURL := bsu.NewContainerURL("")
_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob)
validateStorageError(c, err, azblob.ServiceCodeInvalidQueryParameterValue)
validateStorageError(c, err, ServiceCodeInvalidQueryParameterValue)
}
func (s *aztestsSuite) TestContainerCreateNameCollision(c *chk.C) {
@ -74,16 +71,16 @@ func (s *aztestsSuite) TestContainerCreateNameCollision(c *chk.C) {
defer deleteContainer(c, containerURL)
containerURL = bsu.NewContainerURL(containerName)
_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob)
validateStorageError(c, err, azblob.ServiceCodeContainerAlreadyExists)
validateStorageError(c, err, ServiceCodeContainerAlreadyExists)
}
func (s *aztestsSuite) TestContainerCreateInvalidMetadata(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, azblob.Metadata{"1 foo": "bar"}, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, Metadata{"1 foo": "bar"}, PublicAccessBlob)
c.Assert(err, chk.NotNil)
c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
@ -93,11 +90,11 @@ func (s *aztestsSuite) TestContainerCreateNilMetadata(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, nil, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, nil, PublicAccessBlob)
defer deleteContainer(c, containerURL)
c.Assert(err, chk.IsNil)
response, err := containerURL.GetProperties(ctx, azblob.LeaseAccessConditions{})
response, err := containerURL.GetProperties(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(response.NewMetadata(), chk.HasLen, 0)
}
@ -106,11 +103,11 @@ func (s *aztestsSuite) TestContainerCreateEmptyMetadata(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob)
defer deleteContainer(c, containerURL)
c.Assert(err, chk.IsNil)
response, err := containerURL.GetProperties(ctx, azblob.LeaseAccessConditions{})
response, err := containerURL.GetProperties(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(response.NewMetadata(), chk.HasLen, 0)
}
@ -122,24 +119,24 @@ func (s *aztestsSuite) TestContainerCreateAccessContainer(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, nil, azblob.PublicAccessContainer)
_, err := containerURL.Create(ctx, nil, PublicAccessContainer)
defer deleteContainer(c, containerURL)
c.Assert(err, chk.IsNil)
blobURL := containerURL.NewBlockBlobURL(blobPrefix)
blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), azblob.BlobHTTPHeaders{},
basicMetadata, azblob.BlobAccessConditions{})
blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), BlobHTTPHeaders{},
basicMetadata, BlobAccessConditions{})
// Anonymous enumeration should be valid with container access
containerURL2 := azblob.NewContainerURL(containerURL.URL(), azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{}))
response, err := containerURL2.ListBlobsFlatSegment(ctx, azblob.Marker{},
azblob.ListBlobsSegmentOptions{})
containerURL2 := NewContainerURL(containerURL.URL(), NewPipeline(NewAnonymousCredential(), PipelineOptions{}))
response, err := containerURL2.ListBlobsFlatSegment(ctx, Marker{},
ListBlobsSegmentOptions{})
c.Assert(err, chk.IsNil)
c.Assert(response.Segment.BlobItems[0].Name, chk.Equals, blobPrefix)
// Getting blob data anonymously should still be valid with container access
blobURL2 := containerURL2.NewBlockBlobURL(blobPrefix)
resp, err := blobURL2.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL2.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
}
@ -148,22 +145,22 @@ func (s *aztestsSuite) TestContainerCreateAccessBlob(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, nil, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, nil, PublicAccessBlob)
defer deleteContainer(c, containerURL)
c.Assert(err, chk.IsNil)
blobURL := containerURL.NewBlockBlobURL(blobPrefix)
blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), azblob.BlobHTTPHeaders{},
basicMetadata, azblob.BlobAccessConditions{})
blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), BlobHTTPHeaders{},
basicMetadata, BlobAccessConditions{})
// Reference the same container URL but with anonymous credentials
containerURL2 := azblob.NewContainerURL(containerURL.URL(), azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{}))
_, err = containerURL2.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
validateStorageError(c, err, azblob.ServiceCodeResourceNotFound) // Listing blobs is not publicly accessible
containerURL2 := NewContainerURL(containerURL.URL(), NewPipeline(NewAnonymousCredential(), PipelineOptions{}))
_, err = containerURL2.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{})
validateStorageError(c, err, ServiceCodeResourceNotFound) // Listing blobs is not publicly accessible
// Accessing blob specific data should be public
blobURL2 := containerURL2.NewBlockBlobURL(blobPrefix)
resp, err := blobURL2.GetProperties(ctx, azblob.BlobAccessConditions{})
resp, err := blobURL2.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
}
@ -172,37 +169,37 @@ func (s *aztestsSuite) TestContainerCreateAccessNone(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, nil, azblob.PublicAccessNone)
_, err := containerURL.Create(ctx, nil, PublicAccessNone)
defer deleteContainer(c, containerURL)
blobURL := containerURL.NewBlockBlobURL(blobPrefix)
blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), azblob.BlobHTTPHeaders{},
basicMetadata, azblob.BlobAccessConditions{})
blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), BlobHTTPHeaders{},
basicMetadata, BlobAccessConditions{})
// Reference the same container URL but with anonymous credentials
containerURL2 := azblob.NewContainerURL(containerURL.URL(), azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{}))
containerURL2 := NewContainerURL(containerURL.URL(), NewPipeline(NewAnonymousCredential(), PipelineOptions{}))
// Listing blobs is not public
_, err = containerURL2.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
validateStorageError(c, err, azblob.ServiceCodeResourceNotFound)
_, err = containerURL2.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{})
validateStorageError(c, err, ServiceCodeResourceNotFound)
// Blob data is not public
blobURL2 := containerURL2.NewBlockBlobURL(blobPrefix)
_, err = blobURL2.GetProperties(ctx, azblob.BlobAccessConditions{})
_, err = blobURL2.GetProperties(ctx, BlobAccessConditions{})
c.Assert(err, chk.NotNil)
serr := err.(azblob.StorageError)
serr := err.(StorageError)
c.Assert(serr.Response().StatusCode, chk.Equals, 404) // HEAD request does not return a status code
}
func validateContainerDeleted(c *chk.C, containerURL azblob.ContainerURL) {
_, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeContainerNotFound)
func validateContainerDeleted(c *chk.C, containerURL ContainerURL) {
_, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
validateStorageError(c, err, ServiceCodeContainerNotFound)
}
func (s *aztestsSuite) TestContainerDelete(c *chk.C) {
bsu := getBSU()
containerURL, _ := createNewContainer(c, bsu)
_, err := containerURL.Delete(ctx, azblob.ContainerAccessConditions{})
_, err := containerURL.Delete(ctx, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
validateContainerDeleted(c, containerURL)
@ -212,8 +209,8 @@ func (s *aztestsSuite) TestContainerDeleteNonExistant(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Delete(ctx, azblob.ContainerAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeContainerNotFound)
_, err := containerURL.Delete(ctx, ContainerAccessConditions{})
validateStorageError(c, err, ServiceCodeContainerNotFound)
}
func (s *aztestsSuite) TestContainerDeleteIfModifiedSinceTrue(c *chk.C) {
@ -222,7 +219,7 @@ func (s *aztestsSuite) TestContainerDeleteIfModifiedSinceTrue(c *chk.C) {
containerURL, _ := createNewContainer(c, bsu)
_, err := containerURL.Delete(ctx,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateContainerDeleted(c, containerURL)
}
@ -236,8 +233,8 @@ func (s *aztestsSuite) TestContainerDeleteIfModifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := containerURL.Delete(ctx,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestContainerDeleteIfUnModifiedSinceTrue(c *chk.C) {
@ -246,7 +243,7 @@ func (s *aztestsSuite) TestContainerDeleteIfUnModifiedSinceTrue(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := containerURL.Delete(ctx,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
validateContainerDeleted(c, containerURL)
@ -261,8 +258,8 @@ func (s *aztestsSuite) TestContainerDeleteIfUnModifiedSinceFalse(c *chk.C) {
defer deleteContainer(c, containerURL)
_, err := containerURL.Delete(ctx,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestContainerAccessConditionsUnsupportedConditions(c *chk.C) {
@ -272,9 +269,9 @@ func (s *aztestsSuite) TestContainerAccessConditionsUnsupportedConditions(c *chk
containerURL, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL)
invalidEtag := azblob.ETag("invalid")
invalidEtag := ETag("invalid")
_, err := containerURL.SetMetadata(ctx, basicMetadata,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: invalidEtag}})
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: invalidEtag}})
c.Assert(err, chk.Not(chk.Equals), nil)
}
@ -284,7 +281,7 @@ func (s *aztestsSuite) TestContainerListBlobsNonexistantPrefix(c *chk.C) {
defer deleteContainer(c, containerURL)
createNewBlockBlob(c, containerURL)
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{Prefix: blobPrefix + blobPrefix})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{Prefix: blobPrefix + blobPrefix})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 0)
@ -296,7 +293,7 @@ func (s *aztestsSuite) TestContainerListBlobsSpecificValidPrefix(c *chk.C) {
defer deleteContainer(c, containerURL)
_, blobName := createNewBlockBlob(c, containerURL)
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{Prefix: blobPrefix})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{Prefix: blobPrefix})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 1)
@ -312,7 +309,7 @@ func (s *aztestsSuite) TestContainerListBlobsValidDelimiter(c *chk.C) {
createBlockBlobWithPrefix(c, containerURL, "b/1")
_, blobName := createBlockBlobWithPrefix(c, containerURL, "blob")
resp, err := containerURL.ListBlobsHierarchySegment(ctx, azblob.Marker{}, "/", azblob.ListBlobsSegmentOptions{})
resp, err := containerURL.ListBlobsHierarchySegment(ctx, Marker{}, "/", ListBlobsSegmentOptions{})
c.Assert(err, chk.IsNil)
c.Assert(len(resp.Segment.BlobItems), chk.Equals, 1)
@ -327,7 +324,7 @@ func (s *aztestsSuite) TestContainerListBlobsWithSnapshots(c *chk.C) {
containerURL, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL)
_, err := containerURL.ListBlobsHierarchySegment(ctx, azblob.Marker{}, "/", azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Snapshots: true}})
_, err := containerURL.ListBlobsHierarchySegment(ctx, Marker{}, "/", ListBlobsSegmentOptions{Details: BlobListingDetails{Snapshots: true}})
c.Assert(err, chk.Not(chk.Equals), nil)
}
@ -340,7 +337,7 @@ func (s *aztestsSuite) TestContainerListBlobsInvalidDelimiter(c *chk.C) {
createBlockBlobWithPrefix(c, containerURL, "b/1")
createBlockBlobWithPrefix(c, containerURL, "blob")
resp, err := containerURL.ListBlobsHierarchySegment(ctx, azblob.Marker{}, "^", azblob.ListBlobsSegmentOptions{})
resp, err := containerURL.ListBlobsHierarchySegment(ctx, Marker{}, "^", ListBlobsSegmentOptions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 4)
@ -352,10 +349,10 @@ func (s *aztestsSuite) TestContainerListBlobsIncludeTypeMetadata(c *chk.C) {
defer deleteContainer(c, container)
_, blobNameNoMetadata := createBlockBlobWithPrefix(c, container, "a")
blobMetadata, blobNameMetadata := createBlockBlobWithPrefix(c, container, "b")
_, err := blobMetadata.SetMetadata(ctx, azblob.Metadata{"field": "value"}, azblob.BlobAccessConditions{})
_, err := blobMetadata.SetMetadata(ctx, Metadata{"field": "value"}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := container.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Metadata: true}})
resp, err := container.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{Details: BlobListingDetails{Metadata: true}})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobNameNoMetadata)
@ -369,11 +366,11 @@ func (s *aztestsSuite) TestContainerListBlobsIncludeTypeSnapshots(c *chk.C) {
containerURL, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL)
blob, blobName := createNewBlockBlob(c, containerURL)
_, err := blob.CreateSnapshot(ctx, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err := blob.CreateSnapshot(ctx, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{},
azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Snapshots: true}})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{},
ListBlobsSegmentOptions{Details: BlobListingDetails{Snapshots: true}})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 2)
@ -389,11 +386,11 @@ func (s *aztestsSuite) TestContainerListBlobsIncludeTypeCopy(c *chk.C) {
defer deleteContainer(c, containerURL)
blobURL, blobName := createNewBlockBlob(c, containerURL)
blobCopyURL, blobCopyName := createBlockBlobWithPrefix(c, containerURL, "copy")
_, err := blobCopyURL.StartCopyFromURL(ctx, blobURL.URL(), azblob.Metadata{}, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
_, err := blobCopyURL.StartCopyFromURL(ctx, blobURL.URL(), Metadata{}, ModifiedAccessConditions{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{},
azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Copy: true}})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{},
ListBlobsSegmentOptions{Details: BlobListingDetails{Copy: true}})
// These are sufficient to show that the blob copy was in fact included
c.Assert(err, chk.IsNil)
@ -403,7 +400,7 @@ func (s *aztestsSuite) TestContainerListBlobsIncludeTypeCopy(c *chk.C) {
c.Assert(*resp.Segment.BlobItems[0].Properties.ContentLength, chk.Equals, int64(len(blockBlobDefaultData)))
temp := blobURL.URL()
c.Assert(*resp.Segment.BlobItems[0].Properties.CopySource, chk.Equals, temp.String())
c.Assert(resp.Segment.BlobItems[0].Properties.CopyStatus, chk.Equals, azblob.CopyStatusSuccess)
c.Assert(resp.Segment.BlobItems[0].Properties.CopyStatus, chk.Equals, CopyStatusSuccess)
}
func (s *aztestsSuite) TestContainerListBlobsIncludeTypeUncommitted(c *chk.C) {
@ -411,27 +408,27 @@ func (s *aztestsSuite) TestContainerListBlobsIncludeTypeUncommitted(c *chk.C) {
containerURL, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL)
blobURL, blobName := getBlockBlobURL(c, containerURL)
_, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil)
_, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil)
c.Assert(err, chk.IsNil)
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{},
azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{UncommittedBlobs: true}})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{},
ListBlobsSegmentOptions{Details: BlobListingDetails{UncommittedBlobs: true}})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 1)
c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName)
}
func testContainerListBlobsIncludeTypeDeletedImpl(c *chk.C, bsu azblob.ServiceURL) error {
func testContainerListBlobsIncludeTypeDeletedImpl(c *chk.C, bsu ServiceURL) error {
containerURL, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL)
blobURL, _ := createNewBlockBlob(c, containerURL)
_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
_, err := blobURL.Delete(ctx, DeleteSnapshotsOptionNone, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{},
azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Deleted: true}})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{},
ListBlobsSegmentOptions{Details: BlobListingDetails{Deleted: true}})
c.Assert(err, chk.IsNil)
if len(resp.Segment.BlobItems) != 1 {
return errors.New("DeletedBlobNotFound")
@ -447,22 +444,22 @@ func (s *aztestsSuite) TestContainerListBlobsIncludeTypeDeleted(c *chk.C) {
testContainerListBlobsIncludeTypeDeletedImpl, disableSoftDelete)
}
func testContainerListBlobsIncludeMultipleImpl(c *chk.C, bsu azblob.ServiceURL) error {
func testContainerListBlobsIncludeMultipleImpl(c *chk.C, bsu ServiceURL) error {
containerURL, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL)
blobURL, blobName := createBlockBlobWithPrefix(c, containerURL, "z")
_, err := blobURL.CreateSnapshot(ctx, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err := blobURL.CreateSnapshot(ctx, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
blobURL2, blobName2 := createBlockBlobWithPrefix(c, containerURL, "copy")
resp2, err := blobURL2.StartCopyFromURL(ctx, blobURL.URL(), azblob.Metadata{}, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
resp2, err := blobURL2.StartCopyFromURL(ctx, blobURL.URL(), Metadata{}, ModifiedAccessConditions{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
waitForCopy(c, blobURL2, resp2)
blobURL3, blobName3 := createBlockBlobWithPrefix(c, containerURL, "deleted")
_, err = blobURL3.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
_, err = blobURL3.Delete(ctx, DeleteSnapshotsOptionNone, BlobAccessConditions{})
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{},
azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Snapshots: true, Copy: true, Deleted: true}})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{},
ListBlobsSegmentOptions{Details: BlobListingDetails{Snapshots: true, Copy: true, Deleted: true}})
c.Assert(err, chk.IsNil)
if len(resp.Segment.BlobItems) != 5 { // If there are fewer blobs in the container than there should be, it will be because one was permanently deleted.
@ -489,7 +486,7 @@ func (s *aztestsSuite) TestContainerListBlobsMaxResultsNegative(c *chk.C) {
containerURL, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL)
_, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{MaxResults: -2})
_, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: -2})
c.Assert(err, chk.Not(chk.IsNil))
}
@ -499,7 +496,7 @@ func (s *aztestsSuite) TestContainerListBlobsMaxResultsZero(c *chk.C) {
defer deleteContainer(c, containerURL)
createNewBlockBlob(c, containerURL)
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{MaxResults: 0})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 0})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 1)
@ -512,7 +509,7 @@ func (s *aztestsSuite) TestContainerListBlobsMaxResultsInsufficient(c *chk.C) {
_, blobName := createBlockBlobWithPrefix(c, containerURL, "a")
createBlockBlobWithPrefix(c, containerURL, "b")
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{MaxResults: 1})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 1})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 1)
@ -526,7 +523,7 @@ func (s *aztestsSuite) TestContainerListBlobsMaxResultsExact(c *chk.C) {
_, blobName := createBlockBlobWithPrefix(c, containerURL, "a")
_, blobName2 := createBlockBlobWithPrefix(c, containerURL, "b")
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{MaxResults: 2})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 2})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 2)
@ -541,7 +538,7 @@ func (s *aztestsSuite) TestContainerListBlobsMaxResultsSufficient(c *chk.C) {
_, blobName := createBlockBlobWithPrefix(c, containerURL, "a")
_, blobName2 := createBlockBlobWithPrefix(c, containerURL, "b")
resp, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{MaxResults: 3})
resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 3})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems, chk.HasLen, 2)
@ -553,7 +550,7 @@ func (s *aztestsSuite) TestContainerListBlobsNonExistentContainer(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
_, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{})
c.Assert(err, chk.NotNil)
}
@ -564,7 +561,7 @@ func (s *aztestsSuite) TestContainerWithNewPipeline(c *chk.C) {
containerURL, _ := getContainerURL(c, bsu)
containerURL = containerURL.WithPipeline(pipeline)
_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob)
c.Assert(err, chk.NotNil)
c.Assert(err.Error(), chk.Equals, testPipelineMessage)
@ -580,29 +577,29 @@ func (s *aztestsSuite) TestContainerGetSetPermissionsMultiplePolicies(c *chk.C)
start := generateCurrentTimeWithModerateResolution()
expiry := start.Add(5 * time.Minute)
expiry2 := start.Add(time.Minute)
permissions := []azblob.SignedIdentifier{
permissions := []SignedIdentifier{
{ID: "0000",
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry,
Permission: azblob.AccessPolicyPermission{Read: true, Write: true}.String(),
Permission: AccessPolicyPermission{Read: true, Write: true}.String(),
},
},
{ID: "0001",
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry2,
Permission: azblob.AccessPolicyPermission{Read: true}.String(),
Permission: AccessPolicyPermission{Read: true}.String(),
},
},
}
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, permissions,
azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, permissions,
ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.Items, chk.DeepEquals, permissions)
}
@ -610,14 +607,14 @@ func (s *aztestsSuite) TestContainerGetSetPermissionsMultiplePolicies(c *chk.C)
func (s *aztestsSuite) TestContainerGetPermissionsPublicAccessNotNone(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
containerURL.Create(ctx, nil, azblob.PublicAccessBlob) // We create the container explicitly so we can be sure the access policy is not empty
containerURL.Create(ctx, nil, PublicAccessBlob) // We create the container explicitly so we can be sure the access policy is not empty
defer deleteContainer(c, containerURL)
resp, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.BlobPublicAccess(), chk.Equals, azblob.PublicAccessBlob)
c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessBlob)
}
func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessNone(c *chk.C) {
@ -629,21 +626,21 @@ func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessNone(c *chk.C) {
_, blobName := createNewBlockBlob(c, containerURL)
// Container is created with PublicAccessBlob, so setting it to None will actually test that it is changed through this method
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil, azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
pipeline := azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
bsu2 := azblob.NewServiceURL(bsu.URL(), pipeline)
pipeline := NewPipeline(NewAnonymousCredential(), PipelineOptions{})
bsu2 := NewServiceURL(bsu.URL(), pipeline)
containerURL2 := bsu2.NewContainerURL(containerName)
blobURL2 := containerURL2.NewBlockBlobURL(blobName)
_, err = blobURL2.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
_, err = blobURL2.Download(ctx, 0, 0, BlobAccessConditions{}, false)
// Get permissions via the original container URL so the request succeeds
resp, _ := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, _ := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
// If we cannot access a blob's data, we will also not be able to enumerate blobs
validateStorageError(c, err, azblob.ServiceCodeResourceNotFound)
c.Assert(resp.BlobPublicAccess(), chk.Equals, azblob.PublicAccessNone)
validateStorageError(c, err, ServiceCodeResourceNotFound)
c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessNone)
}
func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessBlob(c *chk.C) {
@ -652,12 +649,12 @@ func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessBlob(c *chk.C) {
defer deleteContainer(c, containerURL)
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, nil, azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, nil, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.BlobPublicAccess(), chk.Equals, azblob.PublicAccessBlob)
c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessBlob)
}
func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessContainer(c *chk.C) {
@ -666,12 +663,12 @@ func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessContainer(c *chk.C
defer deleteContainer(c, containerURL)
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessContainer, nil, azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessContainer, nil, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.BlobPublicAccess(), chk.Equals, azblob.PublicAccessContainer)
c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessContainer)
}
func (s *aztestsSuite) TestContainerSetPermissionsACLSinglePolicy(c *chk.C) {
@ -686,18 +683,18 @@ func (s *aztestsSuite) TestContainerSetPermissionsACLSinglePolicy(c *chk.C) {
start := time.Now().UTC().Add(-15 * time.Second)
expiry := start.Add(5 * time.Minute).UTC()
permissions := []azblob.SignedIdentifier{{
permissions := []SignedIdentifier{{
ID: "0000",
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry,
Permission: azblob.AccessPolicyPermission{List: true}.String(),
Permission: AccessPolicyPermission{List: true}.String(),
},
}}
_, err = containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, permissions, azblob.ContainerAccessConditions{})
_, err = containerURL.SetAccessPolicy(ctx, PublicAccessNone, permissions, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
serviceSASValues := azblob.BlobSASSignatureValues{Identifier: "0000", ContainerName: containerName}
serviceSASValues := BlobSASSignatureValues{Identifier: "0000", ContainerName: containerName}
queryParams, err := serviceSASValues.NewSASQueryParameters(credential)
if err != nil {
c.Fatal(err)
@ -705,20 +702,20 @@ func (s *aztestsSuite) TestContainerSetPermissionsACLSinglePolicy(c *chk.C) {
sasURL := bsu.URL()
sasURL.RawQuery = queryParams.Encode()
sasPipeline := azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
sasBlobServiceURL := azblob.NewServiceURL(sasURL, sasPipeline)
sasPipeline := NewPipeline(NewAnonymousCredential(), PipelineOptions{})
sasBlobServiceURL := NewServiceURL(sasURL, sasPipeline)
// Verifies that the SAS can access the resource
sasContainer := sasBlobServiceURL.NewContainerURL(containerName)
resp, err := sasContainer.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
resp, err := sasContainer.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName)
// Verifies that successful sas access is not just because it's public
anonymousBlobService := azblob.NewServiceURL(bsu.URL(), sasPipeline)
anonymousBlobService := NewServiceURL(bsu.URL(), sasPipeline)
anonymousContainer := anonymousBlobService.NewContainerURL(containerName)
_, err = anonymousContainer.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
validateStorageError(c, err, azblob.ServiceCodeResourceNotFound)
_, err = anonymousContainer.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{})
validateStorageError(c, err, ServiceCodeResourceNotFound)
}
func (s *aztestsSuite) TestContainerSetPermissionsACLMoreThanFive(c *chk.C) {
@ -729,20 +726,20 @@ func (s *aztestsSuite) TestContainerSetPermissionsACLMoreThanFive(c *chk.C) {
start := time.Now().UTC()
expiry := start.Add(5 * time.Minute).UTC()
permissions := make([]azblob.SignedIdentifier, 6, 6)
permissions := make([]SignedIdentifier, 6, 6)
for i := 0; i < 6; i++ {
permissions[i] = azblob.SignedIdentifier{
permissions[i] = SignedIdentifier{
ID: "000" + strconv.Itoa(i),
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry,
Permission: azblob.AccessPolicyPermission{List: true}.String(),
Permission: AccessPolicyPermission{List: true}.String(),
},
}
}
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, permissions, azblob.ContainerAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeInvalidXMLDocument)
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{})
validateStorageError(c, err, ServiceCodeInvalidXMLDocument)
}
func (s *aztestsSuite) TestContainerSetPermissionsDeleteAndModifyACL(c *chk.C) {
@ -753,30 +750,30 @@ func (s *aztestsSuite) TestContainerSetPermissionsDeleteAndModifyACL(c *chk.C) {
start := generateCurrentTimeWithModerateResolution()
expiry := start.Add(5 * time.Minute).UTC()
permissions := make([]azblob.SignedIdentifier, 2, 2)
permissions := make([]SignedIdentifier, 2, 2)
for i := 0; i < 2; i++ {
permissions[i] = azblob.SignedIdentifier{
permissions[i] = SignedIdentifier{
ID: "000" + strconv.Itoa(i),
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry,
Permission: azblob.AccessPolicyPermission{List: true}.String(),
Permission: AccessPolicyPermission{List: true}.String(),
},
}
}
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, permissions, azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.Items, chk.DeepEquals, permissions)
permissions = resp.Items[:1] // Delete the first policy by removing it from the slice
permissions[0].ID = "0004" // Modify the remaining policy which is at index 0 in the new slice
_, err = containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, permissions, azblob.ContainerAccessConditions{})
_, err = containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{})
resp, err = containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err = containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.Items, chk.HasLen, 1)
c.Assert(resp.Items, chk.DeepEquals, permissions)
@ -790,25 +787,25 @@ func (s *aztestsSuite) TestContainerSetPermissionsDeleteAllPolicies(c *chk.C) {
start := time.Now().UTC()
expiry := start.Add(5 * time.Minute).UTC()
permissions := make([]azblob.SignedIdentifier, 2, 2)
permissions := make([]SignedIdentifier, 2, 2)
for i := 0; i < 2; i++ {
permissions[i] = azblob.SignedIdentifier{
permissions[i] = SignedIdentifier{
ID: "000" + strconv.Itoa(i),
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry,
Permission: azblob.AccessPolicyPermission{List: true}.String(),
Permission: AccessPolicyPermission{List: true}.String(),
},
}
}
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, permissions, azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
_, err = containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, []azblob.SignedIdentifier{}, azblob.ContainerAccessConditions{})
_, err = containerURL.SetAccessPolicy(ctx, PublicAccessBlob, []SignedIdentifier{}, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.Items, chk.HasLen, 0)
}
@ -822,19 +819,19 @@ func (s *aztestsSuite) TestContainerSetPermissionsInvalidPolicyTimes(c *chk.C) {
// Swap start and expiry
expiry := time.Now().UTC()
start := expiry.Add(5 * time.Minute).UTC()
permissions := make([]azblob.SignedIdentifier, 2, 2)
permissions := make([]SignedIdentifier, 2, 2)
for i := 0; i < 2; i++ {
permissions[i] = azblob.SignedIdentifier{
permissions[i] = SignedIdentifier{
ID: "000" + strconv.Itoa(i),
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry,
Permission: azblob.AccessPolicyPermission{List: true}.String(),
Permission: AccessPolicyPermission{List: true}.String(),
},
}
}
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, permissions, azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
}
@ -844,7 +841,7 @@ func (s *aztestsSuite) TestContainerSetPermissionsNilPolicySlice(c *chk.C) {
defer deleteContainer(c, containerURL)
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, nil, azblob.ContainerAccessConditions{})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, nil, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
}
@ -860,20 +857,20 @@ func (s *aztestsSuite) TestContainerSetPermissionsSignedIdentifierTooLong(c *chk
}
expiry := time.Now().UTC()
start := expiry.Add(5 * time.Minute).UTC()
permissions := make([]azblob.SignedIdentifier, 2, 2)
permissions := make([]SignedIdentifier, 2, 2)
for i := 0; i < 2; i++ {
permissions[i] = azblob.SignedIdentifier{
permissions[i] = SignedIdentifier{
ID: id,
AccessPolicy: azblob.AccessPolicy{
AccessPolicy: AccessPolicy{
Start: start,
Expiry: expiry,
Permission: azblob.AccessPolicyPermission{List: true}.String(),
Permission: AccessPolicyPermission{List: true}.String(),
},
}
}
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, permissions, azblob.ContainerAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeInvalidXMLDocument)
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{})
validateStorageError(c, err, ServiceCodeInvalidXMLDocument)
}
func (s *aztestsSuite) TestContainerSetPermissionsIfModifiedSinceTrue(c *chk.C) {
@ -883,13 +880,13 @@ func (s *aztestsSuite) TestContainerSetPermissionsIfModifiedSinceTrue(c *chk.C)
defer deleteContainer(c, container)
_, err := container.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
_, err := container.SetAccessPolicy(ctx, PublicAccessNone, nil,
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
resp, err := container.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := container.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.BlobPublicAccess(), chk.Equals, azblob.PublicAccessNone)
c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessNone)
}
func (s *aztestsSuite) TestContainerSetPermissionsIfModifiedSinceFalse(c *chk.C) {
@ -900,9 +897,9 @@ func (s *aztestsSuite) TestContainerSetPermissionsIfModifiedSinceFalse(c *chk.C)
currentTime := getRelativeTimeGMT(10)
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil,
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestContainerSetPermissionsIfUnModifiedSinceTrue(c *chk.C) {
@ -913,13 +910,13 @@ func (s *aztestsSuite) TestContainerSetPermissionsIfUnModifiedSinceTrue(c *chk.C
currentTime := getRelativeTimeGMT(10)
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil,
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetAccessPolicy(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.BlobPublicAccess(), chk.Equals, azblob.PublicAccessNone)
c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessNone)
}
func (s *aztestsSuite) TestContainerSetPermissionsIfUnModifiedSinceFalse(c *chk.C) {
@ -930,9 +927,9 @@ func (s *aztestsSuite) TestContainerSetPermissionsIfUnModifiedSinceFalse(c *chk.
defer deleteContainer(c, containerURL)
_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
_, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil,
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestContainerGetPropertiesAndMetadataNoMetadata(c *chk.C) {
@ -941,7 +938,7 @@ func (s *aztestsSuite) TestContainerGetPropertiesAndMetadataNoMetadata(c *chk.C)
defer deleteContainer(c, containerURL)
resp, err := containerURL.GetProperties(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.HasLen, 0)
}
@ -950,21 +947,21 @@ func (s *aztestsSuite) TestContainerGetPropsAndMetaNonExistantContainer(c *chk.C
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.GetProperties(ctx, azblob.LeaseAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeContainerNotFound)
_, err := containerURL.GetProperties(ctx, LeaseAccessConditions{})
validateStorageError(c, err, ServiceCodeContainerNotFound)
}
func (s *aztestsSuite) TestContainerSetMetadataEmpty(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, basicMetadata, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, basicMetadata, PublicAccessBlob)
defer deleteContainer(c, containerURL)
_, err = containerURL.SetMetadata(ctx, azblob.Metadata{}, azblob.ContainerAccessConditions{})
_, err = containerURL.SetMetadata(ctx, Metadata{}, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetProperties(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.HasLen, 0)
}
@ -972,14 +969,14 @@ func (s *aztestsSuite) TestContainerSetMetadataEmpty(c *chk.C) {
func (*aztestsSuite) TestContainerSetMetadataNil(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.Create(ctx, basicMetadata, azblob.PublicAccessBlob)
_, err := containerURL.Create(ctx, basicMetadata, PublicAccessBlob)
defer deleteContainer(c, containerURL)
_, err = containerURL.SetMetadata(ctx, nil, azblob.ContainerAccessConditions{})
_, err = containerURL.SetMetadata(ctx, nil, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetProperties(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.HasLen, 0)
}
@ -990,7 +987,7 @@ func (*aztestsSuite) TestContainerSetMetadataInvalidField(c *chk.C) {
defer deleteContainer(c, containerURL)
_, err := containerURL.SetMetadata(ctx, azblob.Metadata{"!nval!d Field!@#%": "value"}, azblob.ContainerAccessConditions{})
_, err := containerURL.SetMetadata(ctx, Metadata{"!nval!d Field!@#%": "value"}, ContainerAccessConditions{})
c.Assert(err, chk.NotNil)
c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
}
@ -999,8 +996,8 @@ func (*aztestsSuite) TestContainerSetMetadataNonExistant(c *chk.C) {
bsu := getBSU()
containerURL, _ := getContainerURL(c, bsu)
_, err := containerURL.SetMetadata(ctx, nil, azblob.ContainerAccessConditions{})
validateStorageError(c, err, azblob.ServiceCodeContainerNotFound)
_, err := containerURL.SetMetadata(ctx, nil, ContainerAccessConditions{})
validateStorageError(c, err, ServiceCodeContainerNotFound)
}
func (s *aztestsSuite) TestContainerSetMetadataIfModifiedSinceTrue(c *chk.C) {
@ -1012,10 +1009,10 @@ func (s *aztestsSuite) TestContainerSetMetadataIfModifiedSinceTrue(c *chk.C) {
defer deleteContainer(c, containerURL)
_, err := containerURL.SetMetadata(ctx, basicMetadata,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
c.Assert(err, chk.IsNil)
resp, err := containerURL.GetProperties(ctx, azblob.LeaseAccessConditions{})
resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{})
c.Assert(err, chk.IsNil)
c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
@ -1031,9 +1028,9 @@ func (s *aztestsSuite) TestContainerSetMetadataIfModifiedSinceFalse(c *chk.C) {
currentTime := getRelativeTimeGMT(10)
_, err := containerURL.SetMetadata(ctx, basicMetadata,
azblob.ContainerAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
validateStorageError(c, err, ServiceCodeConditionNotMet)
}
func (s *aztestsSuite) TestContainerNewBlobURL(c *chk.C) {
@ -1044,7 +1041,7 @@ func (s *aztestsSuite) TestContainerNewBlobURL(c *chk.C) {
tempBlob := blobURL.URL()
tempContainer := containerURL.URL()
c.Assert(tempBlob.String(), chk.Equals, tempContainer.String()+"/"+blobPrefix)
c.Assert(blobURL, chk.FitsTypeOf, azblob.BlobURL{})
c.Assert(blobURL, chk.FitsTypeOf, BlobURL{})
}
func (s *aztestsSuite) TestContainerNewBlockBlobURL(c *chk.C) {
@ -1055,5 +1052,5 @@ func (s *aztestsSuite) TestContainerNewBlockBlobURL(c *chk.C) {
tempBlob := blobURL.URL()
tempContainer := containerURL.URL()
c.Assert(tempBlob.String(), chk.Equals, tempContainer.String()+"/"+blobPrefix)
c.Assert(blobURL, chk.FitsTypeOf, azblob.BlockBlobURL{})
c.Assert(blobURL, chk.FitsTypeOf, BlockBlobURL{})
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,11 +1,10 @@
package azblob_test
package azblob
import (
"context"
"strings"
"time"
"github.com/Azure/azure-storage-blob-go/azblob"
chk "gopkg.in/check.v1" // go get gopkg.in/check.v1
)
@ -15,28 +14,28 @@ func (s *aztestsSuite) TestGetAccountInfo(c *chk.C) {
// Ensure the call succeeded. Don't test for specific account properties because we can't/don't want to set account properties.
sAccInfo, err := sa.GetAccountInfo(context.Background())
c.Assert(err, chk.IsNil)
c.Assert(*sAccInfo, chk.Not(chk.DeepEquals), azblob.ServiceGetAccountInfoResponse{})
c.Assert(*sAccInfo, chk.Not(chk.DeepEquals), ServiceGetAccountInfoResponse{})
// Test on a container
cURL := sa.NewContainerURL(generateContainerName())
_, err = cURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessNone)
_, err = cURL.Create(ctx, Metadata{}, PublicAccessNone)
c.Assert(err, chk.IsNil)
cAccInfo, err := cURL.GetAccountInfo(ctx)
c.Assert(err, chk.IsNil)
c.Assert(*cAccInfo, chk.Not(chk.DeepEquals), azblob.ContainerGetAccountInfoResponse{})
c.Assert(*cAccInfo, chk.Not(chk.DeepEquals), ContainerGetAccountInfoResponse{})
// test on a block blob URL. They all call the same thing on the base URL, so only one test is needed for that.
bbURL := cURL.NewBlockBlobURL(generateBlobName())
_, err = bbURL.Upload(ctx, strings.NewReader("blah"), azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err = bbURL.Upload(ctx, strings.NewReader("blah"), BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
c.Assert(err, chk.IsNil)
bAccInfo, err := bbURL.GetAccountInfo(ctx)
c.Assert(err, chk.IsNil)
c.Assert(*bAccInfo, chk.Not(chk.DeepEquals), azblob.BlobGetAccountInfoResponse{})
c.Assert(*bAccInfo, chk.Not(chk.DeepEquals), BlobGetAccountInfoResponse{})
}
func (s *aztestsSuite) TestListContainers(c *chk.C) {
sa := getBSU()
resp, err := sa.ListContainersSegment(context.Background(), azblob.Marker{}, azblob.ListContainersSegmentOptions{Prefix: containerPrefix})
resp, err := sa.ListContainersSegment(context.Background(), Marker{}, ListContainersSegmentOptions{Prefix: containerPrefix})
c.Assert(err, chk.IsNil)
c.Assert(resp.Response().StatusCode, chk.Equals, 200)
c.Assert(resp.RequestID(), chk.Not(chk.Equals), "")
@ -47,24 +46,24 @@ func (s *aztestsSuite) TestListContainers(c *chk.C) {
container, name := createNewContainer(c, sa)
defer delContainer(c, container)
md := azblob.Metadata{
md := Metadata{
"foo": "foovalue",
"bar": "barvalue",
}
_, err = container.SetMetadata(context.Background(), md, azblob.ContainerAccessConditions{})
_, err = container.SetMetadata(context.Background(), md, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
resp, err = sa.ListContainersSegment(context.Background(), azblob.Marker{}, azblob.ListContainersSegmentOptions{Detail: azblob.ListContainersDetail{Metadata: true}, Prefix: name})
resp, err = sa.ListContainersSegment(context.Background(), Marker{}, ListContainersSegmentOptions{Detail: ListContainersDetail{Metadata: true}, Prefix: name})
c.Assert(err, chk.IsNil)
c.Assert(resp.ContainerItems, chk.HasLen, 1)
c.Assert(resp.ContainerItems[0].Name, chk.NotNil)
c.Assert(resp.ContainerItems[0].Properties, chk.NotNil)
c.Assert(resp.ContainerItems[0].Properties.LastModified, chk.NotNil)
c.Assert(resp.ContainerItems[0].Properties.Etag, chk.NotNil)
c.Assert(resp.ContainerItems[0].Properties.LeaseStatus, chk.Equals, azblob.LeaseStatusUnlocked)
c.Assert(resp.ContainerItems[0].Properties.LeaseState, chk.Equals, azblob.LeaseStateAvailable)
c.Assert(resp.ContainerItems[0].Properties.LeaseStatus, chk.Equals, LeaseStatusUnlocked)
c.Assert(resp.ContainerItems[0].Properties.LeaseState, chk.Equals, LeaseStateAvailable)
c.Assert(string(resp.ContainerItems[0].Properties.LeaseDuration), chk.Equals, "")
c.Assert(string(resp.ContainerItems[0].Properties.PublicAccess), chk.Equals, string(azblob.PublicAccessNone))
c.Assert(string(resp.ContainerItems[0].Properties.PublicAccess), chk.Equals, string(PublicAccessNone))
c.Assert(resp.ContainerItems[0].Metadata, chk.DeepEquals, md)
}
@ -75,7 +74,7 @@ func (s *aztestsSuite) TestListContainersPaged(c *chk.C) {
const maxResultsPerPage = 2
const pagedContainersPrefix = "azblobspagedtest"
containers := make([]azblob.ContainerURL, numContainers)
containers := make([]ContainerURL, numContainers)
for i := 0; i < numContainers; i++ {
containers[i], _ = createNewContainerWithSuffix(c, sa, pagedContainersPrefix)
}
@ -86,11 +85,11 @@ func (s *aztestsSuite) TestListContainersPaged(c *chk.C) {
}
}()
marker := azblob.Marker{}
marker := Marker{}
iterations := numContainers / maxResultsPerPage
for i := 0; i < iterations; i++ {
resp, err := sa.ListContainersSegment(context.Background(), marker, azblob.ListContainersSegmentOptions{MaxResults: maxResultsPerPage, Prefix: containerPrefix + pagedContainersPrefix})
resp, err := sa.ListContainersSegment(context.Background(), marker, ListContainersSegmentOptions{MaxResults: maxResultsPerPage, Prefix: containerPrefix + pagedContainersPrefix})
c.Assert(err, chk.IsNil)
c.Assert(resp.ContainerItems, chk.HasLen, maxResultsPerPage)
@ -107,7 +106,7 @@ func (s *aztestsSuite) TestAccountListContainersEmptyPrefix(c *chk.C) {
containerURL2, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL2)
response, err := bsu.ListContainersSegment(ctx, azblob.Marker{}, azblob.ListContainersSegmentOptions{})
response, err := bsu.ListContainersSegment(ctx, Marker{}, ListContainersSegmentOptions{})
c.Assert(err, chk.IsNil)
c.Assert(len(response.ContainerItems) >= 2, chk.Equals, true) // The response should contain at least the two created containers. Probably many more
@ -121,12 +120,12 @@ func (s *aztestsSuite) TestAccountListContainersIncludeTypeMetadata(c *chk.C) {
defer deleteContainer(c, containerURLMetadata)
// Test on containers with and without metadata
_, err := containerURLMetadata.SetMetadata(ctx, basicMetadata, azblob.ContainerAccessConditions{})
_, err := containerURLMetadata.SetMetadata(ctx, basicMetadata, ContainerAccessConditions{})
c.Assert(err, chk.IsNil)
// Also validates not specifying MaxResults
response, err := bsu.ListContainersSegment(ctx, azblob.Marker{},
azblob.ListContainersSegmentOptions{Prefix: containerPrefix, Detail: azblob.ListContainersDetail{Metadata: true}})
response, err := bsu.ListContainersSegment(ctx, Marker{},
ListContainersSegmentOptions{Prefix: containerPrefix, Detail: ListContainersDetail{Metadata: true}})
c.Assert(err, chk.IsNil)
c.Assert(response.ContainerItems[0].Name, chk.Equals, nameNoMetadata)
c.Assert(response.ContainerItems[0].Metadata, chk.HasLen, 0)
@ -140,7 +139,7 @@ func (s *aztestsSuite) TestAccountListContainersMaxResultsNegative(c *chk.C) {
defer deleteContainer(c, containerURL)
_, err := bsu.ListContainersSegment(ctx,
azblob.Marker{}, *(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: -2}))
Marker{}, *(&ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: -2}))
c.Assert(err, chk.Not(chk.IsNil))
}
@ -152,7 +151,7 @@ func (s *aztestsSuite) TestAccountListContainersMaxResultsZero(c *chk.C) {
// Max Results = 0 means the value will be ignored, the header not set, and the server default used
resp, err := bsu.ListContainersSegment(ctx,
azblob.Marker{}, *(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 0}))
Marker{}, *(&ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 0}))
c.Assert(err, chk.IsNil)
// There could be existing container
@ -168,7 +167,7 @@ func (s *aztestsSuite) TestAccountListContainersMaxResultsExact(c *chk.C) {
defer deleteContainer(c, containerURL2)
response, err := bsu.ListContainersSegment(ctx,
azblob.Marker{}, *(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 2}))
Marker{}, *(&ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 2}))
c.Assert(err, chk.IsNil)
c.Assert(response.ContainerItems, chk.HasLen, 2)
@ -183,8 +182,8 @@ func (s *aztestsSuite) TestAccountListContainersMaxResultsInsufficient(c *chk.C)
containerURL2, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL2)
response, err := bsu.ListContainersSegment(ctx, azblob.Marker{},
*(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 1}))
response, err := bsu.ListContainersSegment(ctx, Marker{},
*(&ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 1}))
c.Assert(err, chk.IsNil)
c.Assert(len(response.ContainerItems), chk.Equals, 1)
@ -197,8 +196,8 @@ func (s *aztestsSuite) TestAccountListContainersMaxResultsSufficient(c *chk.C) {
containerURL2, _ := createNewContainer(c, bsu)
defer deleteContainer(c, containerURL2)
response, err := bsu.ListContainersSegment(ctx, azblob.Marker{},
*(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 3}))
response, err := bsu.ListContainersSegment(ctx, Marker{},
*(&ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 3}))
c.Assert(err, chk.IsNil)
@ -210,7 +209,7 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicy(c *chk.C) {
bsu := getBSU()
days := int32(5)
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: true, Days: &days}})
c.Assert(err, chk.IsNil)
// From FE, 30 seconds is guaranteed t be enough.
@ -221,7 +220,7 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicy(c *chk.C) {
c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, true)
c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
_, err = bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: false}})
_, err = bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: false}})
c.Assert(err, chk.IsNil)
// From FE, 30 seconds is guaranteed t be enough.
@ -237,7 +236,7 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicyEmpty(c *chk.C) {
bsu := getBSU()
days := int32(5)
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: true, Days: &days}})
c.Assert(err, chk.IsNil)
// From FE, 30 seconds is guaranteed t be enough.
@ -249,7 +248,7 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicyEmpty(c *chk.C) {
c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
// Enabled should default to false and therefore disable the policy
_, err = bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{}})
_, err = bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{}})
c.Assert(err, chk.IsNil)
// From FE, 30 seconds is guaranteed t be enough.
@ -265,7 +264,7 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicyNil(c *chk.C) {
bsu := getBSU()
days := int32(5)
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: true, Days: &days}})
c.Assert(err, chk.IsNil)
// From FE, 30 seconds is guaranteed t be enough.
@ -276,7 +275,7 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicyNil(c *chk.C) {
c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, true)
c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
_, err = bsu.SetProperties(ctx, azblob.StorageServiceProperties{})
_, err = bsu.SetProperties(ctx, StorageServiceProperties{})
c.Assert(err, chk.IsNil)
// From FE, 30 seconds is guaranteed t be enough.
@ -289,14 +288,14 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicyNil(c *chk.C) {
c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
// Disable for other tests
bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: false}})
bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: false}})
}
func (s *aztestsSuite) TestAccountDeleteRetentionPolicyDaysTooSmall(c *chk.C) {
bsu := getBSU()
days := int32(0) // Minimum days is 1. Validated on the client.
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: true, Days: &days}})
c.Assert(strings.Contains(err.Error(), validationErrorSubstring), chk.Equals, true)
}
@ -304,14 +303,14 @@ func (s *aztestsSuite) TestAccountDeleteRetentionPolicyDaysTooLarge(c *chk.C) {
bsu := getBSU()
days := int32(366) // Max days is 365. Left to the service for validation.
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
validateStorageError(c, err, azblob.ServiceCodeInvalidXMLDocument)
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: true, Days: &days}})
validateStorageError(c, err, ServiceCodeInvalidXMLDocument)
}
func (s *aztestsSuite) TestAccountDeleteRetentionPolicyDaysOmitted(c *chk.C) {
bsu := getBSU()
// Days is required if enabled is true.
_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true}})
validateStorageError(c, err, azblob.ServiceCodeInvalidXMLDocument)
_, err := bsu.SetProperties(ctx, StorageServiceProperties{DeleteRetentionPolicy: &RetentionPolicy{Enabled: true}})
validateStorageError(c, err, ServiceCodeInvalidXMLDocument)
}

Просмотреть файл

@ -1,11 +1,11 @@
package azblob_test
package azblob
import (
"bytes"
"github.com/Azure/azure-storage-blob-go/azblob"
chk "gopkg.in/check.v1"
"strings"
"time"
chk "gopkg.in/check.v1"
)
//Creates a container and tests permissions by listing blobs
@ -19,17 +19,17 @@ func (s *aztestsSuite) TestUserDelegationSASContainer(c *chk.C) {
}
// Create pipeline w/ OAuth to handle user delegation key obtaining
p := azblob.NewPipeline(*ocred, azblob.PipelineOptions{})
p := NewPipeline(*ocred, PipelineOptions{})
bsu = bsu.WithPipeline(p)
keyInfo := azblob.NewKeyInfo(currentTime, currentTime.Add(48*time.Hour))
keyInfo := NewKeyInfo(currentTime, currentTime.Add(48*time.Hour))
cudk, err := bsu.GetUserDelegationCredential(ctx, keyInfo, nil, nil)
if err != nil {
c.Fatal(err)
}
cSAS, err := azblob.BlobSASSignatureValues{
Protocol: azblob.SASProtocolHTTPS,
cSAS, err := BlobSASSignatureValues{
Protocol: SASProtocolHTTPS,
StartTime: currentTime,
ExpiryTime: currentTime.Add(24 * time.Hour),
Permissions: "racwdl",
@ -37,11 +37,11 @@ func (s *aztestsSuite) TestUserDelegationSASContainer(c *chk.C) {
}.NewSASQueryParameters(cudk)
// Create anonymous pipeline
p = azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
p = NewPipeline(NewAnonymousCredential(), PipelineOptions{})
// Create the container
_, err = containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessNone)
defer containerURL.Delete(ctx, azblob.ContainerAccessConditions{})
_, err = containerURL.Create(ctx, Metadata{}, PublicAccessNone)
defer containerURL.Delete(ctx, ContainerAccessConditions{})
if err != nil {
c.Fatal(err)
}
@ -49,17 +49,17 @@ func (s *aztestsSuite) TestUserDelegationSASContainer(c *chk.C) {
// Craft a container URL w/ container UDK SAS
cURL := containerURL.URL()
cURL.RawQuery += cSAS.Encode()
cSASURL := azblob.NewContainerURL(cURL, p)
cSASURL := NewContainerURL(cURL, p)
bblob := cSASURL.NewBlockBlobURL("test")
_, err = bblob.Upload(ctx, strings.NewReader("hello world!"), azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err = bblob.Upload(ctx, strings.NewReader("hello world!"), BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{})
if err != nil {
c.Fatal(err)
}
resp, err := bblob.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
resp, err := bblob.Download(ctx, 0, 0, BlobAccessConditions{}, false)
data := &bytes.Buffer{}
body := resp.Body(azblob.RetryReaderOptions{})
body := resp.Body(RetryReaderOptions{})
if body == nil {
c.Fatal("download body was nil")
}
@ -73,7 +73,7 @@ func (s *aztestsSuite) TestUserDelegationSASContainer(c *chk.C) {
}
c.Assert(data.String(), chk.Equals, "hello world!")
_, err = bblob.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
_, err = bblob.Delete(ctx, DeleteSnapshotsOptionNone, BlobAccessConditions{})
if err != nil {
c.Fatal(err)
}
@ -92,19 +92,19 @@ func (s *aztestsSuite) TestUserDelegationSASBlob(c *chk.C) {
}
// Create pipeline to handle requests
p := azblob.NewPipeline(*ocred, azblob.PipelineOptions{})
p := NewPipeline(*ocred, PipelineOptions{})
// Prepare user delegation key
bsu = bsu.WithPipeline(p)
keyInfo := azblob.NewKeyInfo(currentTime, currentTime.Add(48*time.Hour))
keyInfo := NewKeyInfo(currentTime, currentTime.Add(48*time.Hour))
budk, err := bsu.GetUserDelegationCredential(ctx, keyInfo, nil, nil) //MUST have TokenCredential
if err != nil {
c.Fatal(err)
}
// Prepare User Delegation SAS query
bSAS, err := azblob.BlobSASSignatureValues{
Protocol: azblob.SASProtocolHTTPS,
bSAS, err := BlobSASSignatureValues{
Protocol: SASProtocolHTTPS,
StartTime: currentTime,
ExpiryTime: currentTime.Add(24 * time.Hour),
Permissions: "rd",
@ -116,32 +116,32 @@ func (s *aztestsSuite) TestUserDelegationSASBlob(c *chk.C) {
}
// Create pipeline
p = azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
p = NewPipeline(NewAnonymousCredential(), PipelineOptions{})
// Append User Delegation SAS token to URL
bSASParts := azblob.NewBlobURLParts(blobURL.URL())
bSASParts := NewBlobURLParts(blobURL.URL())
bSASParts.SAS = bSAS
bSASURL := azblob.NewBlockBlobURL(bSASParts.URL(), p)
bSASURL := NewBlockBlobURL(bSASParts.URL(), p)
// Create container & upload sample data
_, err = containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessNone)
defer containerURL.Delete(ctx, azblob.ContainerAccessConditions{})
_, err = containerURL.Create(ctx, Metadata{}, PublicAccessNone)
defer containerURL.Delete(ctx, ContainerAccessConditions{})
if err != nil {
c.Fatal(err)
}
data := "Hello World!"
_, err = blobURL.Upload(ctx, strings.NewReader(data), azblob.BlobHTTPHeaders{ContentType: "text/plain"}, azblob.Metadata{}, azblob.BlobAccessConditions{})
_, err = blobURL.Upload(ctx, strings.NewReader(data), BlobHTTPHeaders{ContentType: "text/plain"}, Metadata{}, BlobAccessConditions{})
if err != nil {
c.Fatal(err)
}
// Download data via User Delegation SAS URL; must succeed
downloadResponse, err := bSASURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
downloadResponse, err := bSASURL.Download(ctx, 0, 0, BlobAccessConditions{}, false)
if err != nil {
c.Fatal(err)
}
downloadedData := &bytes.Buffer{}
reader := downloadResponse.Body(azblob.RetryReaderOptions{})
reader := downloadResponse.Body(RetryReaderOptions{})
_, err = downloadedData.ReadFrom(reader)
if err != nil {
c.Fatal(err)
@ -153,7 +153,7 @@ func (s *aztestsSuite) TestUserDelegationSASBlob(c *chk.C) {
c.Assert(data, chk.Equals, downloadedData.String())
// Delete the item using the User Delegation SAS URL; must succeed
_, err = bSASURL.Delete(ctx, azblob.DeleteSnapshotsOptionInclude, azblob.BlobAccessConditions{})
_, err = bSASURL.Delete(ctx, DeleteSnapshotsOptionInclude, BlobAccessConditions{})
if err != nil {
c.Fatal(err)
}

13
go.mod
Просмотреть файл

@ -1,10 +1,13 @@
module github.com/Azure/azure-storage-blob-go
module github.com/Azure/azure-kusto-go
go 1.13
require (
github.com/Azure/azure-pipeline-go v0.2.1
github.com/Azure/go-autorest/autorest/adal v0.8.0
github.com/Azure/go-autorest/autorest v0.10.0 // indirect
github.com/Azure/go-autorest/autorest/adal v0.8.2
github.com/google/uuid v1.1.1
github.com/kr/pretty v0.1.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
github.com/pkg/errors v0.9.1 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
)
go 1.13

24
go.sum
Просмотреть файл

@ -1,23 +1,26 @@
github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo=
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/go-autorest v13.3.0+incompatible h1:8Ix0VdeOllBx9jEcZ2Wb1uqWUpE1awmJiaHztwaJCPk=
github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.2 h1:6AWuh3uWrsZJcNoCHrCF/+g4aKPCU39kaMO6/qrnK/4=
github.com/Azure/go-autorest/autorest v0.10.0 h1:mvdtztBqcL8se7MdrUweNieTNi4kfNG6GOJuurQJpuY=
github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0 h1:CxTzQrySOxDnKpLjFJeZAS5Qrv/qFPkgLjx5bOAi//I=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0=
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -25,9 +28,16 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=