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 }