github.com/seashell-org/golang-migrate/v4@v4.15.3-0.20220722221203-6ab6c6c062d1/source/google_cloud_storage/storage.go (about) 1 package googlecloudstorage 2 3 import ( 4 "fmt" 5 "io" 6 "net/url" 7 "os" 8 "path" 9 "strings" 10 11 "context" 12 13 "cloud.google.com/go/storage" 14 "github.com/seashell-org/golang-migrate/v4/source" 15 "google.golang.org/api/iterator" 16 ) 17 18 func init() { 19 source.Register("gcs", &gcs{}) 20 } 21 22 type gcs struct { 23 bucket *storage.BucketHandle 24 prefix string 25 migrations *source.Migrations 26 } 27 28 func (g *gcs) Open(folder string) (source.Driver, error) { 29 u, err := url.Parse(folder) 30 if err != nil { 31 return nil, err 32 } 33 client, err := storage.NewClient(context.Background()) 34 if err != nil { 35 return nil, err 36 } 37 driver := gcs{ 38 bucket: client.Bucket(u.Host), 39 prefix: strings.Trim(u.Path, "/") + "/", 40 migrations: source.NewMigrations(), 41 } 42 err = driver.loadMigrations() 43 if err != nil { 44 return nil, err 45 } 46 return &driver, nil 47 } 48 49 func (g *gcs) loadMigrations() error { 50 iter := g.bucket.Objects(context.Background(), &storage.Query{ 51 Prefix: g.prefix, 52 Delimiter: "/", 53 }) 54 object, err := iter.Next() 55 for ; err == nil; object, err = iter.Next() { 56 _, fileName := path.Split(object.Name) 57 m, parseErr := source.DefaultParse(fileName) 58 if parseErr != nil { 59 continue 60 } 61 if !g.migrations.Append(m) { 62 return fmt.Errorf("unable to parse file %v", object.Name) 63 } 64 } 65 if err != iterator.Done { 66 return err 67 } 68 return nil 69 } 70 71 func (g *gcs) Close() error { 72 return nil 73 } 74 75 func (g *gcs) First() (uint, error) { 76 v, ok := g.migrations.First() 77 if !ok { 78 return 0, os.ErrNotExist 79 } 80 return v, nil 81 } 82 83 func (g *gcs) Prev(version uint) (uint, error) { 84 v, ok := g.migrations.Prev(version) 85 if !ok { 86 return 0, os.ErrNotExist 87 } 88 return v, nil 89 } 90 91 func (g *gcs) Next(version uint) (uint, error) { 92 v, ok := g.migrations.Next(version) 93 if !ok { 94 return 0, os.ErrNotExist 95 } 96 return v, nil 97 } 98 99 func (g *gcs) ReadUp(version uint) (io.ReadCloser, string, error) { 100 if m, ok := g.migrations.Up(version); ok { 101 return g.open(m) 102 } 103 return nil, "", os.ErrNotExist 104 } 105 106 func (g *gcs) ReadDown(version uint) (io.ReadCloser, string, error) { 107 if m, ok := g.migrations.Down(version); ok { 108 return g.open(m) 109 } 110 return nil, "", os.ErrNotExist 111 } 112 113 func (g *gcs) open(m *source.Migration) (io.ReadCloser, string, error) { 114 objectPath := path.Join(g.prefix, m.Raw) 115 reader, err := g.bucket.Object(objectPath).NewReader(context.Background()) 116 if err != nil { 117 return nil, "", err 118 } 119 return reader, m.Identifier, nil 120 }