fix: ensure layer media type matches image media type if oci image (#2700)
test: add to ensure media type being saved
This commit is contained in:
		
							parent
							
								
									2c5a6d6af4
								
							
						
					
					
						commit
						e9787f85d4
					
				|  | @ -516,7 +516,16 @@ func (s *stageBuilder) saveSnapshotToLayer(tarPath string) (v1.Layer, error) { | ||||||
| 		layerOpts = append(layerOpts, tarball.WithCompression("zstd"), tarball.WithMediaType(types.OCILayerZStd)) | 		layerOpts = append(layerOpts, tarball.WithCompression("zstd"), tarball.WithMediaType(types.OCILayerZStd)) | ||||||
| 
 | 
 | ||||||
| 	case config.GZip: | 	case config.GZip: | ||||||
|  | 
 | ||||||
| 		// layer already gzipped by default
 | 		// layer already gzipped by default
 | ||||||
|  | 	default: | ||||||
|  | 		mt, err := s.image.MediaType() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		if strings.Contains(string(mt), types.OCIVendorPrefix) { | ||||||
|  | 			layerOpts = append(layerOpts, tarball.WithMediaType(types.OCILayer)) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	layer, err := tarball.LayerFromFile(tarPath, layerOpts...) | 	layer, err := tarball.LayerFromFile(tarPath, layerOpts...) | ||||||
|  | @ -684,7 +693,6 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		stageIdxToDigest[fmt.Sprintf("%d", sb.stage.Index)] = d.String() | 		stageIdxToDigest[fmt.Sprintf("%d", sb.stage.Index)] = d.String() | ||||||
| 		logrus.Debugf("Mapping stage idx %v to digest %v", sb.stage.Index, d.String()) | 		logrus.Debugf("Mapping stage idx %v to digest %v", sb.stage.Index, d.String()) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ import ( | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/empty" | 	"github.com/google/go-containerregistry/pkg/v1/empty" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/mutate" | 	"github.com/google/go-containerregistry/pkg/v1/mutate" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/partial" | 	"github.com/google/go-containerregistry/pkg/v1/partial" | ||||||
|  | 	"github.com/google/go-containerregistry/pkg/v1/types" | ||||||
| 	"github.com/moby/buildkit/frontend/dockerfile/instructions" | 	"github.com/moby/buildkit/frontend/dockerfile/instructions" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -1702,3 +1703,147 @@ func Test_ResolveCrossStageInstructions(t *testing.T) { | ||||||
| 		testutil.CheckDeepEqual(t, expectedMap, stageToIdx) | 		testutil.CheckDeepEqual(t, expectedMap, stageToIdx) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | type ociFakeImage struct { | ||||||
|  | 	*fakeImage | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f ociFakeImage) MediaType() (types.MediaType, error) { | ||||||
|  | 	return types.OCIManifestSchema1, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func Test_stageBuilder_saveSnapshotToLayer(t *testing.T) { | ||||||
|  | 	dir, files := tempDirAndFile(t) | ||||||
|  | 	type fields struct { | ||||||
|  | 		stage            config.KanikoStage | ||||||
|  | 		image            v1.Image | ||||||
|  | 		cf               *v1.ConfigFile | ||||||
|  | 		baseImageDigest  string | ||||||
|  | 		finalCacheKey    string | ||||||
|  | 		opts             *config.KanikoOptions | ||||||
|  | 		fileContext      util.FileContext | ||||||
|  | 		cmds             []commands.DockerCommand | ||||||
|  | 		args             *dockerfile.BuildArgs | ||||||
|  | 		crossStageDeps   map[int][]string | ||||||
|  | 		digestToCacheKey map[string]string | ||||||
|  | 		stageIdxToDigest map[string]string | ||||||
|  | 		snapshotter      snapShotter | ||||||
|  | 		layerCache       cache.LayerCache | ||||||
|  | 		pushLayerToCache cachePusher | ||||||
|  | 	} | ||||||
|  | 	type args struct { | ||||||
|  | 		tarPath string | ||||||
|  | 	} | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name              string | ||||||
|  | 		fields            fields | ||||||
|  | 		args              args | ||||||
|  | 		expectedMediaType types.MediaType | ||||||
|  | 		expectedDiff      v1.Hash | ||||||
|  | 		expectedDigest    v1.Hash | ||||||
|  | 		wantErr           bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "oci image", | ||||||
|  | 			fields: fields{ | ||||||
|  | 				image: ociFakeImage{}, | ||||||
|  | 				opts: &config.KanikoOptions{ | ||||||
|  | 					ForceBuildMetadata: true, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			args: args{ | ||||||
|  | 				tarPath: filepath.Join(dir, files[0]), | ||||||
|  | 			}, | ||||||
|  | 			expectedMediaType: types.OCILayer, | ||||||
|  | 			expectedDiff: v1.Hash{ | ||||||
|  | 				Algorithm: "sha256", | ||||||
|  | 				Hex:       "404cdd7bc109c432f8cc2443b45bcfe95980f5107215c645236e577929ac3e52", | ||||||
|  | 			}, | ||||||
|  | 			expectedDigest: v1.Hash{ | ||||||
|  | 				Algorithm: "sha256", | ||||||
|  | 				Hex:       "1dc5887a31ec6b388646be46c5f0b2036f92f4cbba50d12163a8be4074565a91", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "docker image", | ||||||
|  | 			fields: fields{ | ||||||
|  | 				image: fakeImage{}, | ||||||
|  | 				opts: &config.KanikoOptions{ | ||||||
|  | 					ForceBuildMetadata: true, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			args: args{ | ||||||
|  | 				tarPath: filepath.Join(dir, files[0]), | ||||||
|  | 			}, | ||||||
|  | 			expectedMediaType: types.DockerLayer, | ||||||
|  | 			expectedDiff: v1.Hash{ | ||||||
|  | 				Algorithm: "sha256", | ||||||
|  | 				Hex:       "404cdd7bc109c432f8cc2443b45bcfe95980f5107215c645236e577929ac3e52", | ||||||
|  | 			}, | ||||||
|  | 			expectedDigest: v1.Hash{ | ||||||
|  | 				Algorithm: "sha256", | ||||||
|  | 				Hex:       "1dc5887a31ec6b388646be46c5f0b2036f92f4cbba50d12163a8be4074565a91", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "oci image, zstd compression", | ||||||
|  | 			fields: fields{ | ||||||
|  | 				image: fakeImage{}, | ||||||
|  | 				opts: &config.KanikoOptions{ | ||||||
|  | 					ForceBuildMetadata: true, | ||||||
|  | 					Compression:        config.ZStd, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			args: args{ | ||||||
|  | 				tarPath: filepath.Join(dir, files[0]), | ||||||
|  | 			}, | ||||||
|  | 			expectedMediaType: types.OCILayerZStd, | ||||||
|  | 			expectedDiff: v1.Hash{ | ||||||
|  | 				Algorithm: "sha256", | ||||||
|  | 				Hex:       "404cdd7bc109c432f8cc2443b45bcfe95980f5107215c645236e577929ac3e52", | ||||||
|  | 			}, | ||||||
|  | 			expectedDigest: v1.Hash{ | ||||||
|  | 				Algorithm: "sha256", | ||||||
|  | 				Hex:       "28369c11d9b68c9877781eaf4d8faffb4d0ada1900a1fb83ad452e58a072b45b", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			s := &stageBuilder{ | ||||||
|  | 				stage:            tt.fields.stage, | ||||||
|  | 				image:            tt.fields.image, | ||||||
|  | 				cf:               tt.fields.cf, | ||||||
|  | 				baseImageDigest:  tt.fields.baseImageDigest, | ||||||
|  | 				finalCacheKey:    tt.fields.finalCacheKey, | ||||||
|  | 				opts:             tt.fields.opts, | ||||||
|  | 				fileContext:      tt.fields.fileContext, | ||||||
|  | 				cmds:             tt.fields.cmds, | ||||||
|  | 				args:             tt.fields.args, | ||||||
|  | 				crossStageDeps:   tt.fields.crossStageDeps, | ||||||
|  | 				digestToCacheKey: tt.fields.digestToCacheKey, | ||||||
|  | 				stageIdxToDigest: tt.fields.stageIdxToDigest, | ||||||
|  | 				snapshotter:      tt.fields.snapshotter, | ||||||
|  | 				layerCache:       tt.fields.layerCache, | ||||||
|  | 				pushLayerToCache: tt.fields.pushLayerToCache, | ||||||
|  | 			} | ||||||
|  | 			got, err := s.saveSnapshotToLayer(tt.args.tarPath) | ||||||
|  | 			if (err != nil) != tt.wantErr { | ||||||
|  | 				t.Errorf("stageBuilder.saveSnapshotToLayer() error = %v, wantErr %v", err, tt.wantErr) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if mt, _ := got.MediaType(); mt != tt.expectedMediaType { | ||||||
|  | 				t.Errorf("expected mediatype %s, got %s", tt.expectedMediaType, mt) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if diff, _ := got.DiffID(); diff != tt.expectedDiff { | ||||||
|  | 				t.Errorf("expected diff %s, got %s", tt.expectedDiff, diff) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if digest, _ := got.Digest(); digest != tt.expectedDigest { | ||||||
|  | 				t.Errorf("expected digest %s, got %s", tt.expectedDigest, digest) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue