Skip to content

Instantly share code, notes, and snippets.

@wolfeidau
Created July 19, 2021 05:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wolfeidau/46eda378604ecd70986010817e801c8a to your computer and use it in GitHub Desktop.
Save wolfeidau/46eda378604ecd70986010817e801c8a to your computer and use it in GitHub Desktop.
Simple app which copies files to S3 with content type and modtime
package main
import (
"context"
"fmt"
"io/fs"
"mime"
"os"
"path/filepath"
"time"
"github.com/alecthomas/kong"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go/aws"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
const (
metaMtime = "Mtime" // the meta key to store mtime in - e.g. X-Amz-Meta-Mtime
)
var (
cfg struct {
Debug bool
Version kong.VersionFlag
InputPath string
Bucket string
Prefix string
}
version string
)
func main() {
kong.Parse(
&cfg,
kong.Vars{"version": version}, // bind a var for version
)
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
zerolog.SetGlobalLevel(zerolog.InfoLevel)
if cfg.Debug {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
ctx := context.Background()
awscfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
log.Fatal().Err(err).Msg("failed to configure sdk")
}
client := s3.NewFromConfig(awscfg)
err = fs.WalkDir(os.DirFS(cfg.InputPath), ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
fin, err := d.Info()
if err != nil {
return err
}
fmt.Printf("path=%q, isDir=%v mod=%v\n", path, d.IsDir(), fin.ModTime())
if !d.IsDir() {
f, err := os.Open(filepath.Join(cfg.InputPath, path))
if err != nil {
return err
}
defer f.Close()
meta := map[string]string{
"metaMtime": fin.ModTime().Format(time.RFC3339Nano),
}
input := &s3.PutObjectInput{
Bucket: aws.String(cfg.Bucket),
Key: aws.String(filepath.Join(cfg.Prefix, path)),
Body: f,
Metadata: meta,
ContentType: aws.String(mime.TypeByExtension(filepath.Ext(path))),
}
res, err := client.PutObject(ctx, input)
if err != nil {
return err
}
log.Info().Str("path", path).Str("ETag", aws.StringValue(res.ETag)).Str("VersionId", aws.StringValue(res.VersionId)).Msg("object uploaded")
}
return nil
})
if err != nil {
log.Fatal().Err(err).Msg("failed to walk path")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment