/
s3.go
108 lines (90 loc) · 2.56 KB
/
s3.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package config
import (
"bytes"
"errors"
"io"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/spf13/viper"
)
// S3ConfigSource loads a YAML config from a file in a AWS S3 bucket.
type S3ConfigSource struct {
// Aws config for S3 access.
config *aws.Config
// Bucket the config file is located in.
bucket string
// Path and file name for a config file.
key string
}
// NewS3ConfigSource returns a new S3 config source which uses passed config file from given S4 bucket.
// If region is nil it will try to get current aws region from environment var AWS_REGION.
func NewS3ConfigSource(bucket, key string, region *string) ConfigSource {
if region == nil {
if envRegion, ok := os.LookupEnv("AWS_REGION"); ok {
region = &envRegion
}
}
return &S3ConfigSource{
config: &aws.Config{
Region: region,
},
bucket: bucket,
key: key,
}
}
// NewS3ConfigSourceFromEnv creates a new S3 config source using values defined by
// environment variables.
//
// AWS_REGION - Defines AWS region the bucket is related to
// GO_CONFIG_S3_BUCKET - Bucket where config file are located
// GO_CONFIG_S3_KEY - Config file in a bucket
func NewS3ConfigSourceFromEnv() (ConfigSource, error) {
region, ok := os.LookupEnv("AWS_REGION")
if !ok {
return nil, errors.New("Missing AWS_REGION")
}
bucket, ok := os.LookupEnv("GO_CONFIG_S3_BUCKET")
if !ok {
return nil, errors.New("Missing GO_CONFIG_S3_BUCKET")
}
key, ok := os.LookupEnv("GO_CONFIG_S3_KEY")
if !ok {
return nil, errors.New("Missing GO_CONFIG_S3_KEY")
}
return &S3ConfigSource{
config: &aws.Config{
Region: ®ion,
},
bucket: bucket,
key: key,
}, nil
}
// Load config file from S3 and pass it to a ViperConfig.
func (source *S3ConfigSource) Load() (Config, error) {
config := viper.New()
config.SetConfigType("yaml")
reader, err := source.readConfig()
if err != nil {
return nil, err
}
return newViperConfigFromReader(reader)
}
// readConfig downloads defined config file from AWS S3 bucket and
// uses file content to create a new ViperConfig.
func (source *S3ConfigSource) readConfig() (io.Reader, error) {
downloader := s3manager.NewDownloader(session.Must(session.NewSession(source.config)))
buf := &aws.WriteAtBuffer{}
var reader io.Reader
_, err := downloader.Download(buf,
&s3.GetObjectInput{
Bucket: aws.String(source.bucket),
Key: aws.String(source.key),
})
if err == nil {
reader = bytes.NewReader(buf.Bytes())
}
return reader, err
}