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 }