2025-01-14 15:42:43 +00:00
|
|
|
package configfetcher
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/aws/aws-sdk-go-v2/config"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
type S3Fetcher struct {
|
|
|
|
S3Client *s3.Client
|
|
|
|
}
|
|
|
|
|
2025-01-15 01:13:05 +00:00
|
|
|
// NewS3Fetcher creates a new instance of S3Fetcher with the provided options.
|
|
|
|
func NewS3Fetcher(options ...Option) (*S3Fetcher, error) {
|
|
|
|
cfg := &FetcherConfig{}
|
|
|
|
for _, opt := range options {
|
|
|
|
opt(cfg)
|
2025-01-14 15:42:43 +00:00
|
|
|
}
|
2025-01-15 01:13:05 +00:00
|
|
|
|
|
|
|
// Initialize S3 client if not provided
|
|
|
|
if cfg.S3Client == nil {
|
|
|
|
awsCfg, err := config.LoadDefaultConfig(context.TODO())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cfg.S3Client = s3.NewFromConfig(awsCfg)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &S3Fetcher{S3Client: cfg.S3Client}, nil
|
2025-01-14 15:42:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch retrieves the configuration from an S3 bucket
|
|
|
|
// Source should be in the format "bucket-name/object-key"
|
|
|
|
func (s *S3Fetcher) Fetch(source string) ([]byte, error) {
|
|
|
|
bucket, key, err := parseS3Source(source)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := s.S3Client.GetObject(context.TODO(), &s3.GetObjectInput{
|
|
|
|
Bucket: &bucket,
|
|
|
|
Key: &key,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
_, err = buf.ReadFrom(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse decodes the raw data into the provided target structure
|
|
|
|
func (s *S3Fetcher) Parse(data []byte, target interface{}) error {
|
|
|
|
return yaml.Unmarshal(data, target)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper function to parse S3 source into bucket and key
|
|
|
|
func parseS3Source(source string) (bucket, key string, err error) {
|
|
|
|
parts := strings.SplitN(source, "/", 2)
|
|
|
|
if len(parts) != 2 {
|
|
|
|
return "", "", errors.New("invalid S3 source format, expected bucket-name/object-key")
|
|
|
|
}
|
|
|
|
return parts[0], parts[1], nil
|
|
|
|
}
|