github.com/shiroyuki/docker@v1.9.0/integration-cli/registry.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  
    11  	"github.com/docker/distribution/digest"
    12  	"github.com/go-check/check"
    13  )
    14  
    15  const v2binary = "registry-v2"
    16  
    17  type testRegistryV2 struct {
    18  	cmd *exec.Cmd
    19  	dir string
    20  }
    21  
    22  func newTestRegistryV2(c *check.C) (*testRegistryV2, error) {
    23  	template := `version: 0.1
    24  loglevel: debug
    25  storage:
    26      filesystem:
    27          rootdirectory: %s
    28  http:
    29      addr: %s`
    30  	tmp, err := ioutil.TempDir("", "registry-test-")
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	confPath := filepath.Join(tmp, "config.yaml")
    35  	config, err := os.Create(confPath)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL); err != nil {
    40  		os.RemoveAll(tmp)
    41  		return nil, err
    42  	}
    43  
    44  	cmd := exec.Command(v2binary, confPath)
    45  	if err := cmd.Start(); err != nil {
    46  		os.RemoveAll(tmp)
    47  		if os.IsNotExist(err) {
    48  			c.Skip(err.Error())
    49  		}
    50  		return nil, err
    51  	}
    52  	return &testRegistryV2{
    53  		cmd: cmd,
    54  		dir: tmp,
    55  	}, nil
    56  }
    57  
    58  func (t *testRegistryV2) Ping() error {
    59  	// We always ping through HTTP for our test registry.
    60  	resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL))
    61  	if err != nil {
    62  		return err
    63  	}
    64  	if resp.StatusCode != 200 {
    65  		return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
    66  	}
    67  	return nil
    68  }
    69  
    70  func (t *testRegistryV2) Close() {
    71  	t.cmd.Process.Kill()
    72  	os.RemoveAll(t.dir)
    73  }
    74  
    75  func (t *testRegistryV2) getBlobFilename(blobDigest digest.Digest) string {
    76  	// Split the digest into it's algorithm and hex components.
    77  	dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex()
    78  
    79  	// The path to the target blob data looks something like:
    80  	//   baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data"
    81  	return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", t.dir, dgstAlg, dgstHex[:2], dgstHex)
    82  }
    83  
    84  func (t *testRegistryV2) readBlobContents(c *check.C, blobDigest digest.Digest) []byte {
    85  	// Load the target manifest blob.
    86  	manifestBlob, err := ioutil.ReadFile(t.getBlobFilename(blobDigest))
    87  	if err != nil {
    88  		c.Fatalf("unable to read blob: %s", err)
    89  	}
    90  
    91  	return manifestBlob
    92  }
    93  
    94  func (t *testRegistryV2) writeBlobContents(c *check.C, blobDigest digest.Digest, data []byte) {
    95  	if err := ioutil.WriteFile(t.getBlobFilename(blobDigest), data, os.FileMode(0644)); err != nil {
    96  		c.Fatalf("unable to write malicious data blob: %s", err)
    97  	}
    98  }
    99  
   100  func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest) (undo func()) {
   101  	tempFile, err := ioutil.TempFile("", "registry-temp-blob-")
   102  	if err != nil {
   103  		c.Fatalf("unable to get temporary blob file: %s", err)
   104  	}
   105  	tempFile.Close()
   106  
   107  	blobFilename := t.getBlobFilename(blobDigest)
   108  
   109  	// Move the existing data file aside, so that we can replace it with a
   110  	// another blob of data.
   111  	if err := os.Rename(blobFilename, tempFile.Name()); err != nil {
   112  		os.Remove(tempFile.Name())
   113  		c.Fatalf("unable to move data blob: %s", err)
   114  	}
   115  
   116  	return func() {
   117  		os.Rename(tempFile.Name(), blobFilename)
   118  		os.Remove(tempFile.Name())
   119  	}
   120  }