github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/internal/pipe/blob/blob_minio_test.go (about) 1 package blob 2 3 // this is pretty much copied from the s3 pipe to ensure both work the same way 4 // only differences are that it sets `blobs` instead of `s3` on test cases and 5 // the test setup and teardown 6 7 import ( 8 "fmt" 9 "io" 10 "net" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "strings" 15 "testing" 16 "time" 17 18 "github.com/goreleaser/goreleaser/internal/artifact" 19 "github.com/goreleaser/goreleaser/pkg/config" 20 "github.com/goreleaser/goreleaser/pkg/context" 21 "github.com/stretchr/testify/require" 22 "gocloud.dev/blob" 23 ) 24 25 const ( 26 minioUser = "minio" 27 minioPwd = "miniostorage" 28 ) 29 30 func TestMinioUpload(t *testing.T) { 31 listen := randomListen(t) 32 folder := t.TempDir() 33 srcpath := filepath.Join(folder, "source.tar.gz") 34 tgzpath := filepath.Join(folder, "bin.tar.gz") 35 debpath := filepath.Join(folder, "bin.deb") 36 checkpath := filepath.Join(folder, "check.txt") 37 require.NoError(t, os.WriteFile(checkpath, []byte("fake checksums"), 0o744)) 38 require.NoError(t, os.WriteFile(srcpath, []byte("fake\nsrc"), 0o744)) 39 require.NoError(t, os.WriteFile(tgzpath, []byte("fake\ntargz"), 0o744)) 40 require.NoError(t, os.WriteFile(debpath, []byte("fake\ndeb"), 0o744)) 41 ctx := context.New(config.Project{ 42 Dist: folder, 43 ProjectName: "testupload", 44 Blobs: []config.Blob{ 45 { 46 Provider: "s3", 47 Bucket: "test", 48 Region: "us-east", 49 Endpoint: "http://" + listen, 50 IDs: []string{"foo", "bar"}, 51 }, 52 }, 53 }) 54 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 55 ctx.Artifacts.Add(&artifact.Artifact{ 56 Type: artifact.Checksum, 57 Name: "checksum.txt", 58 Path: checkpath, 59 }) 60 ctx.Artifacts.Add(&artifact.Artifact{ 61 Type: artifact.UploadableSourceArchive, 62 Name: "source.tar.gz", 63 Path: srcpath, 64 Extra: map[string]interface{}{ 65 "Format": "tar.gz", 66 }, 67 }) 68 ctx.Artifacts.Add(&artifact.Artifact{ 69 Type: artifact.UploadableArchive, 70 Name: "bin.tar.gz", 71 Path: tgzpath, 72 Extra: map[string]interface{}{ 73 "ID": "foo", 74 }, 75 }) 76 ctx.Artifacts.Add(&artifact.Artifact{ 77 Type: artifact.LinuxPackage, 78 Name: "bin.deb", 79 Path: debpath, 80 Extra: map[string]interface{}{ 81 "ID": "bar", 82 }, 83 }) 84 name := "test_upload" 85 start(t, name, listen) 86 prepareEnv() 87 require.NoError(t, Pipe{}.Default(ctx)) 88 require.NoError(t, Pipe{}.Publish(ctx)) 89 90 require.Subset(t, getFiles(t, ctx, ctx.Config.Blobs[0]), []string{ 91 "testupload/v1.0.0/bin.deb", 92 "testupload/v1.0.0/bin.tar.gz", 93 "testupload/v1.0.0/checksum.txt", 94 "testupload/v1.0.0/source.tar.gz", 95 }) 96 } 97 98 func TestMinioUploadCustomBucketID(t *testing.T) { 99 listen := randomListen(t) 100 folder := t.TempDir() 101 tgzpath := filepath.Join(folder, "bin.tar.gz") 102 debpath := filepath.Join(folder, "bin.deb") 103 require.NoError(t, os.WriteFile(tgzpath, []byte("fake\ntargz"), 0o744)) 104 require.NoError(t, os.WriteFile(debpath, []byte("fake\ndeb"), 0o744)) 105 // Set custom BUCKET_ID env variable. 106 require.NoError(t, os.Setenv("BUCKET_ID", "test")) 107 ctx := context.New(config.Project{ 108 Dist: folder, 109 ProjectName: "testupload", 110 Blobs: []config.Blob{ 111 { 112 Provider: "s3", 113 Bucket: "{{.Env.BUCKET_ID}}", 114 Endpoint: "http://" + listen, 115 }, 116 }, 117 }) 118 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 119 ctx.Artifacts.Add(&artifact.Artifact{ 120 Type: artifact.UploadableArchive, 121 Name: "bin.tar.gz", 122 Path: tgzpath, 123 }) 124 ctx.Artifacts.Add(&artifact.Artifact{ 125 Type: artifact.LinuxPackage, 126 Name: "bin.deb", 127 Path: debpath, 128 }) 129 name := "custom_bucket_id" 130 start(t, name, listen) 131 prepareEnv() 132 require.NoError(t, Pipe{}.Default(ctx)) 133 require.NoError(t, Pipe{}.Publish(ctx)) 134 } 135 136 func TestMinioUploadRootFolder(t *testing.T) { 137 listen := randomListen(t) 138 folder := t.TempDir() 139 tgzpath := filepath.Join(folder, "bin.tar.gz") 140 debpath := filepath.Join(folder, "bin.deb") 141 require.NoError(t, os.WriteFile(tgzpath, []byte("fake\ntargz"), 0o744)) 142 require.NoError(t, os.WriteFile(debpath, []byte("fake\ndeb"), 0o744)) 143 ctx := context.New(config.Project{ 144 Dist: folder, 145 ProjectName: "testupload", 146 Blobs: []config.Blob{ 147 { 148 Provider: "s3", 149 Bucket: "test", 150 Folder: "/", 151 Endpoint: "http://" + listen, 152 }, 153 }, 154 }) 155 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 156 ctx.Artifacts.Add(&artifact.Artifact{ 157 Type: artifact.UploadableArchive, 158 Name: "bin.tar.gz", 159 Path: tgzpath, 160 }) 161 ctx.Artifacts.Add(&artifact.Artifact{ 162 Type: artifact.LinuxPackage, 163 Name: "bin.deb", 164 Path: debpath, 165 }) 166 name := "root_folder" 167 start(t, name, listen) 168 prepareEnv() 169 require.NoError(t, Pipe{}.Default(ctx)) 170 require.NoError(t, Pipe{}.Publish(ctx)) 171 } 172 173 func TestMinioUploadInvalidCustomBucketID(t *testing.T) { 174 listen := randomListen(t) 175 folder := t.TempDir() 176 tgzpath := filepath.Join(folder, "bin.tar.gz") 177 debpath := filepath.Join(folder, "bin.deb") 178 require.NoError(t, os.WriteFile(tgzpath, []byte("fake\ntargz"), 0o744)) 179 require.NoError(t, os.WriteFile(debpath, []byte("fake\ndeb"), 0o744)) 180 ctx := context.New(config.Project{ 181 Dist: folder, 182 ProjectName: "testupload", 183 Blobs: []config.Blob{ 184 { 185 Provider: "s3", 186 Bucket: "{{.Bad}}", 187 Endpoint: "http://" + listen, 188 }, 189 }, 190 }) 191 ctx.Git = context.GitInfo{CurrentTag: "v1.1.0"} 192 ctx.Artifacts.Add(&artifact.Artifact{ 193 Type: artifact.UploadableArchive, 194 Name: "bin.tar.gz", 195 Path: tgzpath, 196 }) 197 ctx.Artifacts.Add(&artifact.Artifact{ 198 Type: artifact.LinuxPackage, 199 Name: "bin.deb", 200 Path: debpath, 201 }) 202 name := "invalid_bucket_id" 203 start(t, name, listen) 204 prepareEnv() 205 require.NoError(t, Pipe{}.Default(ctx)) 206 require.Error(t, Pipe{}.Publish(ctx)) 207 } 208 209 func randomListen(t *testing.T) string { 210 t.Helper() 211 listener, err := net.Listen("tcp", "127.0.0.1:0") 212 require.NoError(t, err) 213 listener.Close() 214 return listener.Addr().String() 215 } 216 217 func prepareEnv() { 218 os.Setenv("AWS_ACCESS_KEY_ID", minioUser) 219 os.Setenv("AWS_SECRET_ACCESS_KEY", minioPwd) 220 os.Setenv("AWS_REGION", "us-east-1") 221 } 222 223 func start(tb testing.TB, name, listen string) { 224 tb.Helper() 225 226 data := filepath.Join(os.TempDir(), name) 227 tb.Cleanup(func() { 228 mc(tb, name, "mc rb --force local/test") 229 if out, err := exec.Command("docker", "stop", name).CombinedOutput(); err != nil { 230 tb.Fatalf("failed to stop minio: %s", string(out)) 231 } 232 if err := os.RemoveAll(data); err != nil { 233 tb.Logf("failed to remove %s", data) 234 } 235 }) 236 237 if out, err := exec.Command( 238 "docker", "run", "-d", "--rm", 239 "-v", data+":/data", 240 "--name", name, 241 "-p", listen+":9000", 242 "-e", "MINIO_ROOT_USER="+minioUser, 243 "-e", "MINIO_ROOT_PASSWORD="+minioPwd, 244 "--health-interval", "1s", 245 "--health-cmd=curl --silent --fail http://localhost:9000/minio/health/ready || exit 1", 246 "minio/minio", 247 "server", "/data", "--console-address", ":9001", 248 ).CombinedOutput(); err != nil { 249 tb.Fatalf("failed to start minio: %s", string(out)) 250 } 251 252 for range time.Tick(time.Second) { 253 out, err := exec.Command("docker", "inspect", "--format='{{json .State.Health}}'", name).CombinedOutput() 254 if err != nil { 255 tb.Fatalf("failed to check minio status: %s", string(out)) 256 } 257 if strings.Contains(string(out), `"Status":"healthy"`) { 258 tb.Log("minio is healthy") 259 break 260 } 261 tb.Log("waiting for minio to be healthy") 262 } 263 264 mc(tb, name, "mc mb local/test") 265 } 266 267 func mc(tb testing.TB, name, cmd string) { 268 tb.Helper() 269 270 if out, err := exec.Command( 271 "docker", "run", "--rm", 272 "--link", name, 273 "--entrypoint", "sh", 274 "minio/mc", 275 "-c", fmt.Sprintf( 276 "mc config host add local http://%s:9000 %s %s; %s", 277 name, minioUser, minioPwd, cmd, 278 ), 279 ).CombinedOutput(); err != nil { 280 tb.Fatalf("failed to create test bucket: %s", string(out)) 281 } 282 } 283 284 func getFiles(t *testing.T, ctx *context.Context, cfg config.Blob) []string { 285 t.Helper() 286 url, err := urlFor(ctx, cfg) 287 require.NoError(t, err) 288 conn, err := blob.OpenBucket(ctx, url) 289 require.NoError(t, err) 290 defer conn.Close() 291 iter := conn.List(nil) 292 var files []string 293 for { 294 file, err := iter.Next(ctx) 295 if err != nil && err == io.EOF { 296 break 297 } 298 require.NoError(t, err) 299 files = append(files, file.Key) 300 } 301 return files 302 }