github.com/lazarenkoa/migrate@v3.5.4+incompatible/source/aws_s3/s3.go (about) 1 package awss3 2 3 import ( 4 "fmt" 5 "io" 6 "net/url" 7 "os" 8 "path" 9 "strings" 10 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/aws/session" 13 "github.com/aws/aws-sdk-go/service/s3" 14 "github.com/aws/aws-sdk-go/service/s3/s3iface" 15 "github.com/golang-migrate/migrate/source" 16 ) 17 18 func init() { 19 source.Register("s3", &s3Driver{}) 20 } 21 22 type s3Driver struct { 23 s3client s3iface.S3API 24 bucket string 25 prefix string 26 migrations *source.Migrations 27 } 28 29 func (s *s3Driver) Open(folder string) (source.Driver, error) { 30 u, err := url.Parse(folder) 31 if err != nil { 32 return nil, err 33 } 34 sess, err := session.NewSession() 35 if err != nil { 36 return nil, err 37 } 38 driver := s3Driver{ 39 bucket: u.Host, 40 prefix: strings.Trim(u.Path, "/") + "/", 41 s3client: s3.New(sess), 42 migrations: source.NewMigrations(), 43 } 44 err = driver.loadMigrations() 45 if err != nil { 46 return nil, err 47 } 48 return &driver, nil 49 } 50 51 func (s *s3Driver) loadMigrations() error { 52 output, err := s.s3client.ListObjects(&s3.ListObjectsInput{ 53 Bucket: aws.String(s.bucket), 54 Prefix: aws.String(s.prefix), 55 Delimiter: aws.String("/"), 56 }) 57 if err != nil { 58 return err 59 } 60 for _, object := range output.Contents { 61 _, fileName := path.Split(aws.StringValue(object.Key)) 62 m, err := source.DefaultParse(fileName) 63 if err != nil { 64 continue 65 } 66 if !s.migrations.Append(m) { 67 return fmt.Errorf("unable to parse file %v", aws.StringValue(object.Key)) 68 } 69 } 70 return nil 71 } 72 73 func (s *s3Driver) Close() error { 74 return nil 75 } 76 77 func (s *s3Driver) First() (uint, error) { 78 v, ok := s.migrations.First() 79 if !ok { 80 return 0, os.ErrNotExist 81 } 82 return v, nil 83 } 84 85 func (s *s3Driver) Prev(version uint) (uint, error) { 86 v, ok := s.migrations.Prev(version) 87 if !ok { 88 return 0, os.ErrNotExist 89 } 90 return v, nil 91 } 92 93 func (s *s3Driver) Next(version uint) (uint, error) { 94 v, ok := s.migrations.Next(version) 95 if !ok { 96 return 0, os.ErrNotExist 97 } 98 return v, nil 99 } 100 101 func (s *s3Driver) ReadUp(version uint) (io.ReadCloser, string, error) { 102 if m, ok := s.migrations.Up(version); ok { 103 return s.open(m) 104 } 105 return nil, "", os.ErrNotExist 106 } 107 108 func (s *s3Driver) ReadDown(version uint) (io.ReadCloser, string, error) { 109 if m, ok := s.migrations.Down(version); ok { 110 return s.open(m) 111 } 112 return nil, "", os.ErrNotExist 113 } 114 115 func (s *s3Driver) open(m *source.Migration) (io.ReadCloser, string, error) { 116 key := path.Join(s.prefix, m.Raw) 117 object, err := s.s3client.GetObject(&s3.GetObjectInput{ 118 Bucket: aws.String(s.bucket), 119 Key: aws.String(key), 120 }) 121 if err != nil { 122 return nil, "", err 123 } 124 return object.Body, m.Identifier, nil 125 }