194 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| //go:build !remote
 | |
| 
 | |
| package libimage
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/containers/common/pkg/config"
 | |
| 	"github.com/containers/image/v5/pkg/compression"
 | |
| 	"github.com/containers/image/v5/types"
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| func TestPush(t *testing.T) {
 | |
| 	runtime := testNewRuntime(t)
 | |
| 	ctx := context.Background()
 | |
| 
 | |
| 	// Prefetch alpine.
 | |
| 	pullOptions := &PullOptions{}
 | |
| 	pullOptions.Writer = os.Stdout
 | |
| 	_, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	pushOptions := &PushOptions{}
 | |
| 	pushOptions.Writer = os.Stdout
 | |
| 
 | |
| 	workdir := t.TempDir()
 | |
| 
 | |
| 	for _, test := range []struct {
 | |
| 		source      string
 | |
| 		destination string
 | |
| 		expectError bool
 | |
| 	}{
 | |
| 		{"alpine", "dir:" + workdir + "/dir", false},
 | |
| 		{"alpine", "oci:" + workdir + "/oci", false},
 | |
| 		{"alpine", "oci-archive:" + workdir + "/oci-archive", false},
 | |
| 		{"alpine", "docker-archive:" + workdir + "/docker-archive", false},
 | |
| 		{"alpine", "containers-storage:localhost/another:alpine", false},
 | |
| 	} {
 | |
| 		_, err := runtime.Push(ctx, test.source, test.destination, pushOptions)
 | |
| 		if test.expectError {
 | |
| 			require.Error(t, err, "%v", test)
 | |
| 			continue
 | |
| 		}
 | |
| 		require.NoError(t, err, "%v", test)
 | |
| 		pulledImages, err := runtime.Pull(ctx, test.destination, config.PullPolicyAlways, pullOptions)
 | |
| 		require.NoError(t, err, "%v", test)
 | |
| 		require.Len(t, pulledImages, 1, "%v", test)
 | |
| 	}
 | |
| 
 | |
| 	// Now there should only be two images: alpine in Docker format and
 | |
| 	// alpine in OCI format.
 | |
| 	listOptions := ListImagesOptions{SetListData: true}
 | |
| 	listedImages, err := runtime.ListImages(ctx, nil, &listOptions)
 | |
| 	require.NoError(t, err, "error listing images")
 | |
| 	require.Len(t, listedImages, 2, "there should only be two images (alpine in Docke/OCI)")
 | |
| 	for _, image := range listedImages {
 | |
| 		require.NotNil(t, image.ListData.IsDangling, "IsDangling should be set")
 | |
| 	}
 | |
| 
 | |
| 	// And now remove all of them.
 | |
| 	rmReports, rmErrors := runtime.RemoveImages(ctx, nil, nil)
 | |
| 	require.Len(t, rmErrors, 0)
 | |
| 	require.Len(t, rmReports, 2)
 | |
| 
 | |
| 	for i, image := range listedImages {
 | |
| 		require.Equal(t, image.ID(), rmReports[i].ID)
 | |
| 		require.True(t, rmReports[i].Removed)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPushOtherPlatform(t *testing.T) {
 | |
| 	runtime := testNewRuntime(t)
 | |
| 	ctx := context.Background()
 | |
| 
 | |
| 	// Prefetch alpine.
 | |
| 	pullOptions := &PullOptions{}
 | |
| 	pullOptions.Writer = os.Stdout
 | |
| 	pullOptions.Architecture = "arm64"
 | |
| 	pulledImages, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Len(t, pulledImages, 1)
 | |
| 
 | |
| 	data, err := pulledImages[0].Inspect(ctx, nil)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Equal(t, "arm64", data.Architecture)
 | |
| 
 | |
| 	pushOptions := &PushOptions{}
 | |
| 	pushOptions.Writer = os.Stdout
 | |
| 	tmp, err := os.CreateTemp("", "")
 | |
| 	require.NoError(t, err)
 | |
| 	tmp.Close()
 | |
| 	defer os.Remove(tmp.Name())
 | |
| 	_, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "docker-archive:"+tmp.Name(), pushOptions)
 | |
| 	require.NoError(t, err)
 | |
| }
 | |
| 
 | |
| func TestPushWithForceCompression(t *testing.T) {
 | |
| 	runtime := testNewRuntime(t)
 | |
| 	ctx := context.Background()
 | |
| 
 | |
| 	// Prefetch alpine.
 | |
| 	pullOptions := &PullOptions{}
 | |
| 	pullOptions.Writer = os.Stdout
 | |
| 	pullOptions.Architecture = "arm64"
 | |
| 	pulledImages, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Len(t, pulledImages, 1)
 | |
| 
 | |
| 	data, err := pulledImages[0].Inspect(ctx, nil)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Equal(t, "arm64", data.Architecture)
 | |
| 
 | |
| 	// Push newly pulled alpine to directory with uncompressed blobs
 | |
| 	pushOptions := &PushOptions{}
 | |
| 	pushOptions.SystemContext = &types.SystemContext{}
 | |
| 	pushOptions.SystemContext.DirForceDecompress = true
 | |
| 	pushOptions.Writer = os.Stdout
 | |
| 	dirDest := t.TempDir()
 | |
| 	_, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "dir:"+dirDest, pushOptions)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	// Pull uncompressed alpine from `dir:dirDest` as source.
 | |
| 	pullOptions = &PullOptions{}
 | |
| 	pullOptions.Writer = os.Stdout
 | |
| 	pullOptions.Architecture = "arm64"
 | |
| 	pulledImages, err = runtime.Pull(ctx, "dir:"+dirDest, config.PullPolicyAlways, pullOptions)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Len(t, pulledImages, 1)
 | |
| 
 | |
| 	// create `oci` image from uncompressed alpine.
 | |
| 	pushOptions = &PushOptions{}
 | |
| 	pushOptions.OciAcceptUncompressedLayers = true
 | |
| 	pushOptions.Writer = os.Stdout
 | |
| 	ociDest := t.TempDir()
 | |
| 	_, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "oci:"+ociDest, pushOptions)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	// blobs from first push
 | |
| 	entries, err := os.ReadDir(filepath.Join(ociDest, "blobs", "sha256"))
 | |
| 	require.NoError(t, err)
 | |
| 	blobsFirstPush := []string{}
 | |
| 	for _, e := range entries {
 | |
| 		blobsFirstPush = append(blobsFirstPush, e.Name())
 | |
| 	}
 | |
| 
 | |
| 	// Note: Compression is changed from `uncompressed` to `Gzip` but blobs
 | |
| 	// should still be same since `ForceCompressionFormat` is `false`.
 | |
| 	pushOptions = &PushOptions{}
 | |
| 	pushOptions.Writer = os.Stdout
 | |
| 	pushOptions.CompressionFormat = &compression.Gzip
 | |
| 	pushOptions.ForceCompressionFormat = false
 | |
| 	_, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "oci:"+ociDest, pushOptions)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	// blobs from second push
 | |
| 	entries, err = os.ReadDir(filepath.Join(ociDest, "blobs", "sha256"))
 | |
| 	require.NoError(t, err)
 | |
| 	blobsSecondPush := []string{}
 | |
| 	for _, e := range entries {
 | |
| 		blobsSecondPush = append(blobsSecondPush, e.Name())
 | |
| 	}
 | |
| 
 | |
| 	// All blobs of first push should be equivalent to blobs of
 | |
| 	// second push since same compression was used
 | |
| 	assert.Equal(t, blobsSecondPush, blobsFirstPush)
 | |
| 
 | |
| 	// Note: Compression is changed from `uncompressed` to `Gzip` but blobs
 | |
| 	// should still be same since `ForceCompressionFormat` is `false`.
 | |
| 	pushOptions = &PushOptions{}
 | |
| 	pushOptions.Writer = os.Stdout
 | |
| 	pushOptions.CompressionFormat = &compression.Gzip
 | |
| 	pushOptions.ForceCompressionFormat = true
 | |
| 	_, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "oci:"+ociDest, pushOptions)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	// collect blobs from third push
 | |
| 	entries, err = os.ReadDir(filepath.Join(ociDest, "blobs", "sha256"))
 | |
| 	require.NoError(t, err)
 | |
| 	blobsThirdPush := []string{}
 | |
| 	for _, e := range entries {
 | |
| 		blobsThirdPush = append(blobsThirdPush, e.Name())
 | |
| 	}
 | |
| 
 | |
| 	// All blobs of third push should not be equivalent to blobs of
 | |
| 	// first push since new compression was used and `ForceCompressionFormat`
 | |
| 	// was `true`.
 | |
| 	assert.NotEqual(t, blobsThirdPush, blobsFirstPush)
 | |
| }
 |