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 	} }
   |