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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| package main
import ( "bytes" "flag" "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3/s3manager" "gopkg.in/yaml.v2" "io" "io/ioutil" "log" "net/http" "net/url" "os" "os/exec" "path/filepath" "time" )
type Config struct { KeyID string `yaml:"key_id"` KeySec string `yaml:"key_sec"` Endpoint string `yaml:"endpoint"` SrcFolderPath string `yaml:"src_folder_path"` TarPath string `yaml:"tar_path"` ZstdPath string `yaml:"zstd_path"` AgePath string `yaml:"age_path"` AgeKey string `yaml:"age_key"` DstName string `yaml:"dst_name"` BucketName string `yaml:"bucket_name"` PushOverUser string `yaml:"push_over_user"` PushOverToken string `yaml:"push_over_token"` }
func main() { configFile := flag.String("f", "config.yaml", "Path to config file") flag.Parse()
data, err := ioutil.ReadFile(*configFile) if err != nil { log.Fatalf("Error reading config file: %v", err) } var config Config err = yaml.Unmarshal(data, &config) if err != nil { log.Fatalf("Error parsing config file: %v", err) }
tarCmd := exec.Command(config.TarPath, "-c", config.SrcFolderPath) zstdCmd := exec.Command(config.ZstdPath) ageCmd := exec.Command(config.AgePath, "-r", config.AgeKey)
tarOut, _ := tarCmd.StdoutPipe() zstdCmd.Stdin = tarOut
zstdOut, _ := zstdCmd.StdoutPipe() ageCmd.Stdin = zstdOut
encryptedFile := fmt.Sprintf("/tmp/%s_%s.tar.zst.age", time.Now().UTC().Format("20060102150405"), config.DstName) f, err := os.Create(encryptedFile) if err != nil { log.Fatalf("os.Create: %v", err) } defer f.Close() defer os.Remove(encryptedFile)
var buffer bytes.Buffer ageCmd.Stdout = &buffer
if err := tarCmd.Start(); err != nil { log.Fatalf("tarCmd.Start: %v", err) } if err := zstdCmd.Start(); err != nil { log.Fatalf("zstdCmd.Start: %v", err) } if err := ageCmd.Start(); err != nil { log.Fatalf("ageCmd.Start: %v", err) }
if err := tarCmd.Wait(); err != nil { log.Fatalf("tarCmd.Wait: %v", err) } tarOut.Close()
if err := zstdCmd.Wait(); err != nil { log.Fatalf("zstdCmd.Wait: %v", err) } zstdOut.Close()
if err := ageCmd.Wait(); err != nil { log.Fatalf("ageCmd.Wait: %v", err) }
io.Copy(f, &buffer)
err = uploadToS3(encryptedFile, config) if err != nil { log.Fatalf("error uploading file to s3: %v", err) } pushNotify(config) }
func uploadToS3(filename string, config Config) error { sess, _ := session.NewSession(&aws.Config{ Endpoint: aws.String(config.Endpoint), Region: aws.String("us-west-000"), Credentials: credentials.NewStaticCredentials(config.KeyID, config.KeySec, ""), })
file, err := os.Open(filename) if err != nil { return err } defer file.Close()
uploader := s3manager.NewUploader(sess)
_, err = uploader.Upload(&s3manager.UploadInput{ Bucket: aws.String(config.BucketName), Key: aws.String(filepath.Base(filename)), Body: file, })
return err }
func pushNotify(conf Config) { message := fmt.Sprintf("Project %s Backup Success", conf.DstName) client := &http.Client{} _, err := client.PostForm("https://api.pushover.net/1/messages.json", url.Values{"token": {conf.PushOverToken}, "user": {conf.PushOverUser}, "message": {message}}) if err != nil { log.Fatal(err) return } }
|