drone-s3-sync/plugin.go

204 lines
4.0 KiB
Go
Raw Normal View History

2016-07-22 02:27:25 +02:00
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
)
type Plugin struct {
2017-10-22 09:24:40 +02:00
Endpoint string
2016-07-22 02:27:25 +02:00
Key string
Secret string
Bucket string
Region string
Source string
Target string
Delete bool
Access map[string]string
2016-10-19 19:56:28 +02:00
CacheControl map[string]string
2016-07-22 02:27:25 +02:00
ContentType map[string]string
ContentEncoding map[string]string
Metadata map[string]map[string]string
Redirects map[string]string
CloudFrontDistribution string
2016-11-19 14:34:46 +01:00
DryRun bool
2017-10-22 09:24:40 +02:00
PathStyle bool
2016-07-22 02:27:25 +02:00
client AWS
jobs []job
2018-08-15 20:13:06 +02:00
MaxConcurrency int
2016-07-22 02:27:25 +02:00
}
type job struct {
local string
remote string
action string
}
type result struct {
j job
err error
}
var MissingAwsValuesMessage = "Must set 'bucket'"
2016-07-22 02:27:25 +02:00
func (p *Plugin) Exec() error {
err := p.sanitizeInputs()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
2022-05-02 22:43:40 +02:00
p.jobs = make([]job, 1)
2016-07-22 02:27:25 +02:00
p.client = NewAWS(p)
p.createSyncJobs()
p.createInvalidateJob()
p.runJobs()
return nil
}
func (p *Plugin) sanitizeInputs() error {
if len(p.Bucket) == 0 {
2016-07-22 02:27:25 +02:00
return errors.New(MissingAwsValuesMessage)
}
wd, err := os.Getwd()
if err != nil {
return err
}
p.Source = filepath.Join(wd, p.Source)
2022-05-02 22:43:40 +02:00
p.Target = strings.TrimPrefix(p.Target, "/")
2016-07-22 02:27:25 +02:00
return nil
}
func (p *Plugin) createSyncJobs() {
remote, err := p.client.List(p.Target)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
2022-05-02 22:43:40 +02:00
local := make([]string, 1)
2016-07-22 02:27:25 +02:00
err = filepath.Walk(p.Source, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
return err
}
localPath := path
if p.Source != "." {
localPath = strings.TrimPrefix(path, p.Source)
2022-05-02 22:43:40 +02:00
localPath = strings.TrimPrefix(localPath, "/")
2016-07-22 02:27:25 +02:00
}
local = append(local, localPath)
p.jobs = append(p.jobs, job{
local: filepath.Join(p.Source, localPath),
remote: filepath.Join(p.Target, localPath),
action: "upload",
})
return nil
})
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for path, location := range p.Redirects {
path = strings.TrimPrefix(path, "/")
local = append(local, path)
p.jobs = append(p.jobs, job{
local: path,
remote: location,
action: "redirect",
})
}
if p.Delete {
for _, r := range remote {
found := false
2019-01-04 12:08:05 +01:00
rPath := strings.TrimPrefix(r, p.Target+"/")
2016-07-22 02:27:25 +02:00
for _, l := range local {
2019-01-04 12:08:05 +01:00
if l == rPath {
2016-07-22 02:27:25 +02:00
found = true
break
}
}
if !found {
p.jobs = append(p.jobs, job{
local: "",
remote: r,
action: "delete",
})
}
}
}
}
func (p *Plugin) createInvalidateJob() {
if len(p.CloudFrontDistribution) > 0 {
p.jobs = append(p.jobs, job{
local: "",
remote: filepath.Join("/", p.Target, "*"),
action: "invalidateCloudFront",
})
}
}
func (p *Plugin) runJobs() {
client := p.client
2018-08-15 20:13:06 +02:00
jobChan := make(chan struct{}, p.MaxConcurrency)
2016-07-22 02:27:25 +02:00
results := make(chan *result, len(p.jobs))
var invalidateJob *job
fmt.Printf("Synchronizing with bucket \"%s\"\n", p.Bucket)
for _, j := range p.jobs {
jobChan <- struct{}{}
go func(j job) {
var err error
2022-05-02 22:43:40 +02:00
switch j.action {
case "upload":
2016-07-22 02:27:25 +02:00
err = client.Upload(j.local, j.remote)
2022-05-02 22:43:40 +02:00
case "redirect":
2016-07-22 02:27:25 +02:00
err = client.Redirect(j.local, j.remote)
2022-05-02 22:43:40 +02:00
case "delete":
2016-07-22 02:27:25 +02:00
err = client.Delete(j.remote)
2022-05-02 22:43:40 +02:00
case "invalidateCloudFront":
2016-07-22 02:27:25 +02:00
invalidateJob = &j
2022-05-02 22:43:40 +02:00
default:
2016-07-22 02:27:25 +02:00
err = nil
}
results <- &result{j, err}
<-jobChan
}(j)
}
2019-01-09 07:08:40 +01:00
for range p.jobs {
2016-07-22 02:27:25 +02:00
r := <-results
if r.err != nil {
fmt.Printf("ERROR: failed to %s %s to %s: %+v\n", r.j.action, r.j.local, r.j.remote, r.err)
os.Exit(1)
}
}
if invalidateJob != nil {
err := client.Invalidate(invalidateJob.remote)
if err != nil {
fmt.Printf("ERROR: failed to %s %s to %s: %+v\n", invalidateJob.action, invalidateJob.local, invalidateJob.remote, err)
os.Exit(1)
}
}
}
func debug(format string, args ...interface{}) {
if os.Getenv("DEBUG") != "" {
fmt.Printf(format+"\n", args...)
} else {
fmt.Printf(".")
}
}