...

Source file src/github.com/docker/distribution/testutil/tarfile.go

Documentation: github.com/docker/distribution/testutil

     1  package testutil
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	crand "crypto/rand"
     7  	"fmt"
     8  	"io"
     9  	mrand "math/rand"
    10  	"time"
    11  
    12  	"github.com/docker/distribution"
    13  	"github.com/docker/distribution/context"
    14  	"github.com/opencontainers/go-digest"
    15  )
    16  
    17  // CreateRandomTarFile creates a random tarfile, returning it as an
    18  // io.ReadSeeker along with its digest. An error is returned if there is a
    19  // problem generating valid content.
    20  func CreateRandomTarFile() (rs io.ReadSeeker, dgst digest.Digest, err error) {
    21  	nFiles := mrand.Intn(10) + 10
    22  	target := &bytes.Buffer{}
    23  	wr := tar.NewWriter(target)
    24  
    25  	// Perturb this on each iteration of the loop below.
    26  	header := &tar.Header{
    27  		Mode:       0644,
    28  		ModTime:    time.Now(),
    29  		Typeflag:   tar.TypeReg,
    30  		Uname:      "randocalrissian",
    31  		Gname:      "cloudcity",
    32  		AccessTime: time.Now(),
    33  		ChangeTime: time.Now(),
    34  	}
    35  
    36  	for fileNumber := 0; fileNumber < nFiles; fileNumber++ {
    37  		fileSize := mrand.Int63n(1<<20) + 1<<20
    38  
    39  		header.Name = fmt.Sprint(fileNumber)
    40  		header.Size = fileSize
    41  
    42  		if err := wr.WriteHeader(header); err != nil {
    43  			return nil, "", err
    44  		}
    45  
    46  		randomData := make([]byte, fileSize)
    47  
    48  		// Fill up the buffer with some random data.
    49  		n, err := crand.Read(randomData)
    50  
    51  		if n != len(randomData) {
    52  			return nil, "", fmt.Errorf("short read creating random reader: %v bytes != %v bytes", n, len(randomData))
    53  		}
    54  
    55  		if err != nil {
    56  			return nil, "", err
    57  		}
    58  
    59  		nn, err := io.Copy(wr, bytes.NewReader(randomData))
    60  		if nn != fileSize {
    61  			return nil, "", fmt.Errorf("short copy writing random file to tar")
    62  		}
    63  
    64  		if err != nil {
    65  			return nil, "", err
    66  		}
    67  
    68  		if err := wr.Flush(); err != nil {
    69  			return nil, "", err
    70  		}
    71  	}
    72  
    73  	if err := wr.Close(); err != nil {
    74  		return nil, "", err
    75  	}
    76  
    77  	dgst = digest.FromBytes(target.Bytes())
    78  
    79  	return bytes.NewReader(target.Bytes()), dgst, nil
    80  }
    81  
    82  // CreateRandomLayers returns a map of n digests. We don't particularly care
    83  // about the order of said digests (since they're all random anyway).
    84  func CreateRandomLayers(n int) (map[digest.Digest]io.ReadSeeker, error) {
    85  	digestMap := map[digest.Digest]io.ReadSeeker{}
    86  	for i := 0; i < n; i++ {
    87  		rs, ds, err := CreateRandomTarFile()
    88  		if err != nil {
    89  			return nil, fmt.Errorf("unexpected error generating test layer file: %v", err)
    90  		}
    91  
    92  		digestMap[ds] = rs
    93  	}
    94  	return digestMap, nil
    95  }
    96  
    97  // UploadBlobs lets you upload blobs to a repository
    98  func UploadBlobs(repository distribution.Repository, layers map[digest.Digest]io.ReadSeeker) error {
    99  	ctx := context.Background()
   100  	for digest, rs := range layers {
   101  		wr, err := repository.Blobs(ctx).Create(ctx)
   102  		if err != nil {
   103  			return fmt.Errorf("unexpected error creating upload: %v", err)
   104  		}
   105  
   106  		if _, err := io.Copy(wr, rs); err != nil {
   107  			return fmt.Errorf("unexpected error copying to upload: %v", err)
   108  		}
   109  
   110  		if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: digest}); err != nil {
   111  			return fmt.Errorf("unexpected error committinng upload: %v", err)
   112  		}
   113  	}
   114  	return nil
   115  }
   116  

View as plain text