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  }