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