get.porter.sh/porter@v1.3.0/pkg/porter/copy_test.go (about)

     1  package porter
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"get.porter.sh/porter/pkg/cnab"
     9  	cnabtooci "get.porter.sh/porter/pkg/cnab/cnab-to-oci"
    10  	"get.porter.sh/porter/pkg/config"
    11  	"get.porter.sh/porter/tests"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestCopyReferenceOnly(t *testing.T) {
    17  	tests := []struct {
    18  		Name     string
    19  		Ref      string
    20  		Expected bool
    21  	}{
    22  		{
    23  			"valid digested reference",
    24  			"jeremyrickard/porter-do-bundle@sha256:a808aa4e3508d7129742eefda938249574447cce5403dc12d4cbbfe7f4f31e58",
    25  			false,
    26  		},
    27  		{
    28  			"tagged reference",
    29  			"jeremyrickard/porter-do-bundle:v0.1.0",
    30  			false,
    31  		},
    32  		{
    33  			"no tag or digest",
    34  			"porter-do-bundle",
    35  			true,
    36  		},
    37  		{
    38  			"no tag or digest",
    39  			"jeremy/rickard/porter-do-bundle",
    40  			true,
    41  		},
    42  	}
    43  
    44  	for _, test := range tests {
    45  		ref := isCopyReferenceOnly(test.Ref)
    46  		assert.Equal(t, test.Expected, ref, fmt.Sprintf("%s, expected %t, got %t", test.Name, test.Expected, ref))
    47  	}
    48  }
    49  
    50  func TestValidateCopyArgs(t *testing.T) {
    51  
    52  	cfg := config.NewTestConfig(t)
    53  
    54  	tests := []struct {
    55  		Name          string
    56  		Opts          CopyOpts
    57  		ExpectError   bool
    58  		ExpectedError string
    59  	}{
    60  		{
    61  			"valid source and dest",
    62  			CopyOpts{
    63  				Source:      "deislabs/mybuns:v0.1.0",
    64  				Destination: "blah.acr.io",
    65  			},
    66  			false,
    67  			"",
    68  		},
    69  		{
    70  			"valid source digest and tagged destination",
    71  			CopyOpts{
    72  				Source:      "deislabs/mybuns@sha256:bb9b47bb07e8c2f62ea1f617351739b35264f8a6121d79e989cd4e81743afe0a",
    73  				Destination: "blah.acr.io:v0.1.0",
    74  			},
    75  			false,
    76  			"",
    77  		},
    78  		{
    79  			"valid source, empty dest",
    80  			CopyOpts{
    81  				Source: "deislabs/mybuns:v0.1.0",
    82  			},
    83  			true,
    84  			"--destination is required",
    85  		},
    86  		{
    87  			"missing source",
    88  			CopyOpts{
    89  				Source:      "",
    90  				Destination: "blah.acr.io",
    91  			},
    92  			true,
    93  			"invalid value for --source",
    94  		},
    95  		{
    96  			"bad source, invalid digest ref",
    97  			CopyOpts{
    98  				Source:      "deislabs/mybuns@v0.1.0",
    99  				Destination: "blah.acr.io",
   100  			},
   101  			true,
   102  			"invalid value for --source",
   103  		},
   104  		{
   105  			"digest to reference only should fail",
   106  			CopyOpts{
   107  				Source:      "jeremyrickard/porter-do@sha256:bb9b47bb07e8c2f62ea1f617351739b35264f8a6121d79e989cd4e81743afe0a",
   108  				Destination: "blah.acr.io",
   109  			},
   110  			true,
   111  			"--destination must be tagged reference when --source is digested reference",
   112  		},
   113  	}
   114  
   115  	for _, test := range tests {
   116  		err := test.Opts.Validate(cfg.Config)
   117  		if test.ExpectError {
   118  			require.Error(t, err)
   119  			assert.Contains(t, err.Error(), test.ExpectedError)
   120  		} else {
   121  			assert.NoError(t, err)
   122  		}
   123  	}
   124  }
   125  
   126  func TestCopyGenerateBundleRef(t *testing.T) {
   127  	tests := []struct {
   128  		Name     string
   129  		Opts     CopyOpts
   130  		Expected string
   131  		WantErr  string
   132  	}{
   133  		{
   134  			Name: "tag source and dest repo",
   135  			Opts: CopyOpts{
   136  				Source:      "deislabs/mybuns:v0.1.0",
   137  				Destination: "blah.acr.io",
   138  			},
   139  			Expected: "blah.acr.io/mybuns:v0.1.0",
   140  		},
   141  		{
   142  			Name: "tag source and dest tag",
   143  			Opts: CopyOpts{
   144  				Source:      "deislabs/mybuns:v0.1.0",
   145  				Destination: "blah.acr.io/blah:v0.10",
   146  			},
   147  			Expected: "blah.acr.io/blah:v0.10",
   148  		},
   149  		{
   150  			Name: "valid source digest and tagged destination",
   151  			Opts: CopyOpts{
   152  				Source:      "deislabs/mybuns@sha256:bb9b47bb07e8c2f62ea1f617351739b35264f8a6121d79e989cd4e81743afe0a",
   153  				Destination: "blah.acr.io/moreblah:v0.1.0",
   154  			},
   155  			Expected: "blah.acr.io/moreblah:v0.1.0",
   156  		},
   157  		{
   158  			Name: "invalid destination",
   159  			Opts: CopyOpts{
   160  				Source:      "deislabs/mybuns:v0.1.0",
   161  				Destination: "oops/",
   162  			},
   163  			WantErr: "invalid reference format",
   164  		},
   165  	}
   166  	for _, test := range tests {
   167  		t.Run(test.Name, func(t *testing.T) {
   168  			src := cnab.MustParseOCIReference(test.Opts.Source)
   169  			newRef, err := generateNewBundleRef(src, test.Opts.Destination)
   170  			if test.WantErr == "" {
   171  				assert.Equal(t, test.Expected, newRef.String(), fmt.Sprintf("%s: expected %s got %s", test.Name, test.Expected, newRef))
   172  			} else {
   173  				require.Error(t, err)
   174  				assert.Contains(t, err.Error(), test.WantErr)
   175  			}
   176  		})
   177  	}
   178  }
   179  
   180  func TestCopy_ForceOverwrite(t *testing.T) {
   181  	t.Parallel()
   182  
   183  	testcases := []struct {
   184  		name    string
   185  		exists  bool
   186  		force   bool
   187  		wantErr string
   188  	}{
   189  		{name: "bundle doesn't exist, force not set", exists: false, force: false, wantErr: ""},
   190  		{name: "bundle exists, force not set", exists: true, force: false, wantErr: "already exists in the destination registry"},
   191  		{name: "bundle exists, force set", exists: true, force: true},
   192  	}
   193  
   194  	for _, tc := range testcases {
   195  		tc := tc
   196  
   197  		t.Run(tc.name, func(t *testing.T) {
   198  			t.Parallel()
   199  
   200  			ctx := context.Background()
   201  			p := NewTestPorter(t)
   202  			defer p.Close()
   203  
   204  			// Set up that the destination already exists
   205  			p.TestRegistry.MockGetBundleMetadata = func(ctx context.Context, ref cnab.OCIReference, opts cnabtooci.RegistryOptions) (cnabtooci.BundleMetadata, error) {
   206  				if tc.exists {
   207  					return cnabtooci.BundleMetadata{}, nil
   208  				}
   209  				return cnabtooci.BundleMetadata{}, cnabtooci.ErrNotFound{Reference: ref}
   210  			}
   211  
   212  			opts := &CopyOpts{
   213  				Source:      "example1.com/mybuns:v0.1.0",
   214  				Destination: "example2.com/mybuns:v0.1.0",
   215  				Force:       tc.force,
   216  			}
   217  			err := opts.Validate(p.Config)
   218  			require.NoError(t, err)
   219  
   220  			err = p.CopyBundle(ctx, opts)
   221  
   222  			if tc.wantErr == "" {
   223  				require.NoError(t, err, "Copy failed")
   224  			} else {
   225  				tests.RequireErrorContains(t, err, tc.wantErr)
   226  			}
   227  		})
   228  	}
   229  }