github.com/docker/cnab-to-oci@v0.3.0-beta4/remotes/push_test.go (about)

     1  package remotes
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/cnabio/cnab-go/bundle"
    11  	"github.com/docker/cnab-to-oci/converter"
    12  	"github.com/docker/cnab-to-oci/tests"
    13  	"github.com/docker/distribution/reference"
    14  	"github.com/docker/go/canonical/json"
    15  	ocischemav1 "github.com/opencontainers/image-spec/specs-go/v1"
    16  	"gotest.tools/assert"
    17  )
    18  
    19  const (
    20  	expectedBundleManifest = `{
    21    "schemaVersion": 2,
    22    "manifests": [
    23      {
    24        "mediaType":"application/vnd.oci.image.manifest.v1+json",
    25        "digest":"sha256:91ada58e30bc0aea920e69a9356085534ce31c50700e650c96b432fc3a5d1661",
    26        "size":189,
    27        "annotations":{
    28          "io.cnab.manifest.type":"config"
    29        }
    30      },
    31      {
    32        "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    33        "digest": "sha256:d59a1aa7866258751a261bae525a1842c7ff0662d4f34a355d5f36826abc0343",
    34        "size": 506,
    35        "annotations": {
    36          "io.cnab.manifest.type": "invocation"
    37        }
    38      },
    39      {
    40        "mediaType": "application/vnd.oci.image.manifest.v1+json",
    41        "digest": "sha256:d59a1aa7866258751a261bae525a1842c7ff0662d4f34a355d5f36826abc0342",
    42        "size": 507,
    43        "annotations": {
    44          "io.cnab.component.name": "another-image",
    45          "io.cnab.manifest.type": "component"
    46        }
    47      },
    48      {
    49        "mediaType": "application/vnd.oci.image.manifest.v1+json",
    50        "digest": "sha256:d59a1aa7866258751a261bae525a1842c7ff0662d4f34a355d5f36826abc0341",
    51        "size": 507,
    52        "annotations": {
    53          "io.cnab.component.name": "image-1",
    54          "io.cnab.manifest.type": "component"
    55        }
    56      }
    57    ],
    58    "annotations": {
    59      "io.cnab.keywords": "[\"keyword1\",\"keyword2\"]",
    60      "io.cnab.runtime_version": "v1.0.0",
    61      "org.opencontainers.artifactType": "application/vnd.cnab.manifest.v1",
    62      "org.opencontainers.image.authors": "[{\"name\":\"docker\",\"email\":\"docker@docker.com\",\"url\":\"docker.com\"}]",
    63      "org.opencontainers.image.description": "description",
    64      "org.opencontainers.image.title": "my-app",
    65      "org.opencontainers.image.version": "0.1.0"
    66    }
    67  }`
    68  	expectedConfigManifest = `{
    69     "schemaVersion": 2,
    70     "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    71     "config": {
    72        "mediaType": "application/vnd.docker.container.image.v1+json",
    73        "size": 1484,
    74        "digest": "sha256:e978bf2a3c57b25fc3bb7f1adccb6fa0f0284d38163d5faffce7bf5fca3f39b3"
    75     },
    76     "layers": [
    77        {
    78           "mediaType": "application/vnd.docker.container.image.v1+json",
    79           "size": 1484,
    80           "digest": "sha256:e978bf2a3c57b25fc3bb7f1adccb6fa0f0284d38163d5faffce7bf5fca3f39b3"
    81        }
    82     ]
    83  }`
    84  )
    85  
    86  func TestPush(t *testing.T) {
    87  	pusher := &mockPusher{}
    88  	resolver := &mockResolver{pusher: pusher}
    89  	b := tests.MakeTestBundle()
    90  	expectedBundleConfig, err := json.MarshalCanonical(b)
    91  	assert.NilError(t, err)
    92  	ref, err := reference.ParseNamed("my.registry/namespace/my-app:my-tag")
    93  	assert.NilError(t, err)
    94  
    95  	// push the bundle
    96  	_, err = Push(context.Background(), b, tests.MakeRelocationMap(), ref, resolver, true)
    97  	assert.NilError(t, err)
    98  	assert.Equal(t, len(resolver.pushedReferences), 3)
    99  	assert.Equal(t, len(pusher.pushedDescriptors), 3)
   100  	assert.Equal(t, len(pusher.buffers), 3)
   101  
   102  	// check pushed config
   103  	assert.Equal(t, "my.registry/namespace/my-app", resolver.pushedReferences[0])
   104  	assert.Equal(t, converter.CNABConfigMediaType, pusher.pushedDescriptors[0].MediaType)
   105  	assert.Equal(t, oneLiner(string(expectedBundleConfig)), pusher.buffers[0].String())
   106  
   107  	// check pushed config manifest
   108  	assert.Equal(t, "my.registry/namespace/my-app", resolver.pushedReferences[1])
   109  	assert.Equal(t, ocischemav1.MediaTypeImageManifest, pusher.pushedDescriptors[1].MediaType)
   110  
   111  	// check pushed bundle manifest index
   112  	assert.Equal(t, "my.registry/namespace/my-app:my-tag", resolver.pushedReferences[2])
   113  	assert.Equal(t, ocischemav1.MediaTypeImageIndex, pusher.pushedDescriptors[2].MediaType)
   114  	assert.Equal(t, oneLiner(expectedBundleManifest), pusher.buffers[2].String())
   115  }
   116  
   117  func TestFallbackConfigManifest(t *testing.T) {
   118  	// Make the pusher return an error for the first two calls
   119  	// so that the fallbacks kick in and we get the non-oci
   120  	// config manifest.
   121  	pusher := newMockPusher([]error{
   122  		errors.New("1"),
   123  		errors.New("2"),
   124  		nil,
   125  		nil,
   126  		nil,
   127  		nil,
   128  		nil})
   129  	resolver := &mockResolver{pusher: pusher}
   130  	b := tests.MakeTestBundle()
   131  	ref, err := reference.ParseNamed("my.registry/namespace/my-app:my-tag")
   132  	assert.NilError(t, err)
   133  
   134  	// push the bundle
   135  	relocationMap := tests.MakeRelocationMap()
   136  	_, err = Push(context.Background(), b, relocationMap, ref, resolver, true)
   137  	assert.NilError(t, err)
   138  	assert.Equal(t, expectedConfigManifest, pusher.buffers[3].String())
   139  }
   140  
   141  func oneLiner(s string) string {
   142  	return strings.Replace(strings.Replace(s, " ", "", -1), "\n", "", -1)
   143  }
   144  
   145  func ExamplePush() {
   146  	resolver := createExampleResolver()
   147  	b := createExampleBundle()
   148  	ref, err := reference.ParseNamed("my.registry/namespace/my-app:my-tag")
   149  	if err != nil {
   150  		panic(err)
   151  	}
   152  
   153  	// Push the bundle here
   154  	descriptor, err := Push(context.Background(), b, tests.MakeRelocationMap(), ref, resolver, true)
   155  	if err != nil {
   156  		panic(err)
   157  	}
   158  
   159  	bytes, err := json.MarshalIndent(descriptor, "", "  ")
   160  	if err != nil {
   161  		panic(err)
   162  	}
   163  
   164  	fmt.Printf("%s", string(bytes))
   165  
   166  	// Output:
   167  	// {
   168  	//   "mediaType": "application/vnd.oci.image.index.v1+json",
   169  	//   "digest": "sha256:4cfae04045c6f0fd14330ab86dea9694fb19ce9602ba2da0af8c826fc0053631",
   170  	//   "size": 1360
   171  	// }
   172  }
   173  
   174  func createExampleBundle() *bundle.Bundle {
   175  	return tests.MakeTestBundle()
   176  }