github.com/l3x/learn-fp-go@v0.0.0-20171228022418-7639825d0b71/2-design-patterns/ch06-onion-arch/04_onion/src/infrastructure/gcphandler.go (about)

     1  package infrastructure
     2  
     3  import (
     4  	"cloud.google.com/go/storage"
     5  	"context"
     6  	"google.golang.org/api/option"
     7  	"domain"
     8  	"google.golang.org/api/iterator"
     9  	. "utils"
    10  	"io/ioutil"
    11  	"os"
    12  	"io"
    13  	"interfaces"
    14  	"usecases"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  type GcpHandler struct {
    19  	Client *storage.Client
    20  }
    21  
    22  var GcpInteractor *usecases.GcpInteractor
    23  
    24  func NewGcpHandler(keyFile string) (gcpHandler *GcpHandler, err error) {
    25  	ctx := context.Background()
    26  	client, err := storage.NewClient(ctx, option.WithServiceAccountFile(keyFile))
    27  	if err != nil {
    28  		return nil, errors.Wrap(err, "unable to create a new storage client")
    29  	}
    30  	gcpHandler = new(GcpHandler)
    31  	gcpHandler.Client = client
    32  	return
    33  }
    34  
    35  func (handler *GcpHandler) ListBuckets(flowType domain.FlowType, projectId string) (buckets []domain.Bucket, err error) {
    36  	Debug.Printf("Running: ListBuckets(%v, %v)", flowType, projectId)
    37  	client := handler.Client
    38  	ctx := context.Background()
    39  	it := client.Buckets(ctx, projectId)
    40  	for {
    41  		battrs, err := it.Next()
    42  		if err == iterator.Done {
    43  			break
    44  		}
    45  		if err != nil {
    46  			return nil, errors.Wrap(err, "bucket iterator error")
    47  		}
    48  		buckets = append(buckets, domain.Bucket{battrs.Name})
    49  	}
    50  	return
    51  }
    52  
    53  func (handler *GcpHandler) FileExists(fileName string) (fileExists bool, err error) {
    54  	ctx := context.Background()
    55  	bucketName := Config.SourceBucketName
    56  	newFile := domain.NewFile(fileName)
    57  	fullPath := newFile.FullHostPath(Config.GcpSourceDir)
    58  	Debug.Printf("fullPath: %s", fullPath)
    59  	br, err := handler.Client.Bucket(bucketName).Object(fullPath).NewReader(ctx)
    60  	if err != nil {
    61  		return false, errors.Wrapf(err, "bucket reader error for %s", fullPath)
    62  	} else {
    63  		data, err := ioutil.ReadAll(br)
    64  		defer br.Close()
    65  		if err != nil {
    66  			return false, errors.Wrapf(err, "ioutil.ReadAll error for %s", fullPath)
    67  		} else if len(data) == 0 {
    68  			return false, errors.Wrapf(err, "File size must be greater than 0 for %s", fullPath)
    69  		}
    70  	}
    71  	return true, err
    72  }
    73  
    74  func (handler *GcpHandler) GetBucketObject(flowType domain.FlowType, projectId string, bucketName string, fileName string) storage.ObjectHandle {
    75  	client := handler.Client
    76  	fileObject := client.Bucket(bucketName).Object(fileName)
    77  	return *fileObject
    78  }
    79  
    80  func (handler *GcpHandler) DownloadFile(fileName string) (success bool, err error) {
    81  	newFile := domain.NewFile(fileName)
    82  	fullFilePath := newFile.FullHostPath(Config.GcpSourceDir)
    83  	Debug.Printf("fullFilePath: %s", fullFilePath)
    84  	ctx := context.Background()
    85  
    86  	Debug.Printf("Config.GcpSourceProjectId: %s", Config.GcpSourceProjectId)
    87  	Debug.Printf("Config.SourceBucketName: %s", Config.SourceBucketName)
    88  	Debug.Printf("fullFilePath: %s", fullFilePath)
    89  
    90  
    91  	bucketObject := handler.GetBucketObject(domain.SourceFlow, Config.GcpSourceProjectId, Config.SourceBucketName, fullFilePath)
    92  	fr, err := bucketObject.NewReader(ctx)
    93  	if err != nil {
    94  		return false, errors.Wrapf(err, "unable to get file (%s) from bucket(%s)", fullFilePath, Config.SourceBucketName)
    95  	}
    96  	defer fr.Close()
    97  	fileBytes, err := ioutil.ReadAll(fr)
    98  	if err != nil {
    99  		return false, errors.Wrap(err, "ioutil.ReadAll failed")
   100  	}
   101  	logFiles, err := newFile.Parse(fileBytes)
   102  	if err != nil {
   103  		return false, errors.Wrap(err, "newFile.Parse failed")
   104  	}
   105  	success = true
   106  	var logFileName string
   107  	var cachedLogFiles []string
   108  	for i, logFile := range *logFiles {
   109  		logFileName = newFile.FullParsedFileName(i)
   110  		Info.Println("Encoding, caching and saving logFileName: "+logFileName)
   111  		logFileJson, err := logFile.ToJson()
   112  		if err != nil {
   113  			Error.Printf("Unable to encode logFileName (%s) - ERROR: %v", logFileName, err)
   114  			break
   115  		}
   116  		cachedLogFiles = append(cachedLogFiles, logFileJson)
   117  		logFile.Write(logFileName, logFileJson)
   118  	}
   119  	return
   120  }
   121  
   122  func (handler *GcpHandler) UploadFile(fileName string) (success bool, err error) {
   123  	ctx := context.Background()
   124  	newFile := domain.NewFile(fileName)
   125  	newFullPath := newFile.FullLocalPath()
   126  	f, err := os.Open(newFullPath)
   127  	if err != nil {
   128  		return false, errors.Wrapf(err, "unable to open local file: %s", newFullPath)
   129  	}
   130  	defer f.Close()
   131  	bucketObject := handler.GetBucketObject(domain.SinkFlow, Config.GcpSinkProjectId, Config.SinkBucketName, newFile.FullHostPath(Config.GcpSinkDir))
   132  	wc := bucketObject.NewWriter(ctx)
   133  	if _, err = io.Copy(wc, f); err != nil {
   134  		return false, errors.Wrapf(err, "io.Copy failed for %s", newFullPath)
   135  	}
   136  	if err := wc.Close(); err != nil {
   137  		return false, errors.Wrapf(err, "io.Close failed for %s", newFullPath)
   138  	}
   139  	success = true
   140  	return
   141  }
   142  
   143  func GetGcpInteractor() (gcpInteractor *usecases.GcpInteractor, err error) {
   144  	if GcpInteractor == nil {
   145  		sourceHandler, err := NewGcpHandler(Config.GcpSourceKeyFile)
   146  		if err != nil {
   147  			return nil, errors.Wrap(err, "unable to create new source gcp handler")
   148  		}
   149  		sinkHandler, err := NewGcpHandler(Config.GcpSinkKeyFile)
   150  		if err != nil {
   151  			return nil, errors.Wrap(err, "unable to create new sink gcp handler")
   152  		}
   153  		handlers := make(map[string] interfaces.GcpHandler)
   154  		handlers["SourceBucketRepo"] = sourceHandler
   155  		handlers["SinkBucketRepo"] = sinkHandler
   156  		gcpInteractor = new(usecases.GcpInteractor)
   157  		gcpInteractor.SourceBucketRepository = interfaces.NewSourceBucketRepo(handlers)
   158  		gcpInteractor.SinkBucketRepository = interfaces.NewSinkBucketRepo(handlers)
   159  		GcpInteractor = gcpInteractor
   160  	}
   161  	return GcpInteractor, err
   162  }
   163  
   164  
   165  
   166  type List interface {
   167  	Cons(val interface{}) List
   168  	ForEach(f func(interface{}))
   169  	Head() interface{}
   170  	IsNil() bool
   171  	Reverse() List
   172  	Size() int
   173  	Tail() List
   174  }
   175  
   176  type Map interface {
   177  	Delete(key string) Map
   178  	ForEach(f func(key string, val interface{}))
   179  	IsNil() bool
   180  	Keys() []string
   181  	Lookup(key string) (interface{}, bool)
   182  	Set(key string, value interface{}) Map
   183  	Size() int
   184  	String() string
   185  	UnsafeMutableSet(key string, value interface{}) Map
   186  }