174 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
package ocischema
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/docker/distribution"
 | 
						|
	"github.com/opencontainers/go-digest"
 | 
						|
	v1 "github.com/opencontainers/image-spec/specs-go/v1"
 | 
						|
)
 | 
						|
 | 
						|
type mockBlobService struct {
 | 
						|
	descriptors map[digest.Digest]distribution.Descriptor
 | 
						|
}
 | 
						|
 | 
						|
func (bs *mockBlobService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
 | 
						|
	if descriptor, ok := bs.descriptors[dgst]; ok {
 | 
						|
		return descriptor, nil
 | 
						|
	}
 | 
						|
	return distribution.Descriptor{}, distribution.ErrBlobUnknown
 | 
						|
}
 | 
						|
 | 
						|
func (bs *mockBlobService) Get(ctx context.Context, dgst digest.Digest) ([]byte, error) {
 | 
						|
	panic("not implemented")
 | 
						|
}
 | 
						|
 | 
						|
func (bs *mockBlobService) Open(ctx context.Context, dgst digest.Digest) (distribution.ReadSeekCloser, error) {
 | 
						|
	panic("not implemented")
 | 
						|
}
 | 
						|
 | 
						|
func (bs *mockBlobService) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
 | 
						|
	d := distribution.Descriptor{
 | 
						|
		Digest:    digest.FromBytes(p),
 | 
						|
		Size:      int64(len(p)),
 | 
						|
		MediaType: "application/octet-stream",
 | 
						|
	}
 | 
						|
	bs.descriptors[d.Digest] = d
 | 
						|
	return d, nil
 | 
						|
}
 | 
						|
 | 
						|
func (bs *mockBlobService) Create(ctx context.Context, options ...distribution.BlobCreateOption) (distribution.BlobWriter, error) {
 | 
						|
	panic("not implemented")
 | 
						|
}
 | 
						|
 | 
						|
func (bs *mockBlobService) Resume(ctx context.Context, id string) (distribution.BlobWriter, error) {
 | 
						|
	panic("not implemented")
 | 
						|
}
 | 
						|
 | 
						|
func TestBuilder(t *testing.T) {
 | 
						|
	imgJSON := []byte(`{
 | 
						|
    "created": "2015-10-31T22:22:56.015925234Z",
 | 
						|
    "author": "Alyssa P. Hacker <alyspdev@example.com>",
 | 
						|
    "architecture": "amd64",
 | 
						|
    "os": "linux",
 | 
						|
    "config": {
 | 
						|
        "User": "alice",
 | 
						|
        "ExposedPorts": {
 | 
						|
            "8080/tcp": {}
 | 
						|
        },
 | 
						|
        "Env": [
 | 
						|
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
 | 
						|
            "FOO=oci_is_a",
 | 
						|
            "BAR=well_written_spec"
 | 
						|
        ],
 | 
						|
        "Entrypoint": [
 | 
						|
            "/bin/my-app-binary"
 | 
						|
        ],
 | 
						|
        "Cmd": [
 | 
						|
            "--foreground",
 | 
						|
            "--config",
 | 
						|
            "/etc/my-app.d/default.cfg"
 | 
						|
        ],
 | 
						|
        "Volumes": {
 | 
						|
            "/var/job-result-data": {},
 | 
						|
            "/var/log/my-app-logs": {}
 | 
						|
        },
 | 
						|
        "WorkingDir": "/home/alice",
 | 
						|
        "Labels": {
 | 
						|
            "com.example.project.git.url": "https://example.com/project.git",
 | 
						|
            "com.example.project.git.commit": "45a939b2999782a3f005621a8d0f29aa387e1d6b"
 | 
						|
        }
 | 
						|
    },
 | 
						|
    "rootfs": {
 | 
						|
      "diff_ids": [
 | 
						|
        "sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1",
 | 
						|
        "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
 | 
						|
      ],
 | 
						|
      "type": "layers"
 | 
						|
    },
 | 
						|
    "annotations": {
 | 
						|
       "hot": "potato"
 | 
						|
    }
 | 
						|
    "history": [
 | 
						|
      {
 | 
						|
        "created": "2015-10-31T22:22:54.690851953Z",
 | 
						|
        "created_by": "/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /"
 | 
						|
      },
 | 
						|
      {
 | 
						|
        "created": "2015-10-31T22:22:55.613815829Z",
 | 
						|
        "created_by": "/bin/sh -c #(nop) CMD [\"sh\"]",
 | 
						|
        "empty_layer": true
 | 
						|
      }
 | 
						|
    ]
 | 
						|
}`)
 | 
						|
	configDigest := digest.FromBytes(imgJSON)
 | 
						|
 | 
						|
	descriptors := []distribution.Descriptor{
 | 
						|
		{
 | 
						|
			Digest:      digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"),
 | 
						|
			Size:        5312,
 | 
						|
			MediaType:   v1.MediaTypeImageLayerGzip,
 | 
						|
			Annotations: map[string]string{"apple": "orange", "lettuce": "wrap"},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Digest:    digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa"),
 | 
						|
			Size:      235231,
 | 
						|
			MediaType: v1.MediaTypeImageLayerGzip,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Digest:    digest.Digest("sha256:b4ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"),
 | 
						|
			Size:      639152,
 | 
						|
			MediaType: v1.MediaTypeImageLayerGzip,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	annotations := map[string]string{"hot": "potato"}
 | 
						|
 | 
						|
	bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)}
 | 
						|
	builder := NewManifestBuilder(bs, imgJSON, annotations)
 | 
						|
 | 
						|
	for _, d := range descriptors {
 | 
						|
		if err := builder.AppendReference(d); err != nil {
 | 
						|
			t.Fatalf("AppendReference returned error: %v", err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	built, err := builder.Build(context.Background())
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("Build returned error: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	// Check that the config was put in the blob store
 | 
						|
	_, err = bs.Stat(context.Background(), configDigest)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal("config was not put in the blob store")
 | 
						|
	}
 | 
						|
 | 
						|
	manifest := built.(*DeserializedManifest).Manifest
 | 
						|
	if manifest.Annotations["hot"] != "potato" {
 | 
						|
		t.Fatalf("unexpected annotation in manifest: %s", manifest.Annotations["hot"])
 | 
						|
	}
 | 
						|
 | 
						|
	if manifest.Versioned.SchemaVersion != 2 {
 | 
						|
		t.Fatal("SchemaVersion != 2")
 | 
						|
	}
 | 
						|
 | 
						|
	target := manifest.Target()
 | 
						|
	if target.Digest != configDigest {
 | 
						|
		t.Fatalf("unexpected digest in target: %s", target.Digest.String())
 | 
						|
	}
 | 
						|
	if target.MediaType != v1.MediaTypeImageConfig {
 | 
						|
		t.Fatalf("unexpected media type in target: %s", target.MediaType)
 | 
						|
	}
 | 
						|
	if target.Size != 1632 {
 | 
						|
		t.Fatalf("unexpected size in target: %d", target.Size)
 | 
						|
	}
 | 
						|
 | 
						|
	references := manifest.References()
 | 
						|
	expected := append([]distribution.Descriptor{manifest.Target()}, descriptors...)
 | 
						|
	if !reflect.DeepEqual(references, expected) {
 | 
						|
		t.Fatal("References() does not match the descriptors added")
 | 
						|
	}
 | 
						|
}
 |