Logger
							parent
							
								
									7c61f09817
								
							
						
					
					
						commit
						2e90fe12a3
					
				
							
								
								
									
										25
									
								
								Taskfile.yml
								
								
								
								
							
							
						
						
									
										25
									
								
								Taskfile.yml
								
								
								
								
							|  | @ -1,9 +1,26 @@ | ||||||
| version: '3' | version: '3' | ||||||
| 
 | 
 | ||||||
|  | vars: | ||||||
|  |   NAME: code.jhot.me/jhot/docker-s3-backup | ||||||
|  | 
 | ||||||
| tasks: | tasks: | ||||||
|  |   default: | ||||||
|  |     vars: | ||||||
|  |       TAG: latest | ||||||
|   build: |   build: | ||||||
|     cmds: |     cmds: | ||||||
|       - docker buildx build -t {{.NAME}}:{{.TAG}} . |       - docker buildx build --platform linux/amd64,linux/arm64 -t "{{.NAME}}:{{.TAG}}" . | ||||||
|     vars: |   push: | ||||||
|       NAME: docker-s3-backup |     cmds: | ||||||
|       TAG: latest |       - docker push "{{.NAME}}:{{.TAG}}" | ||||||
|  |   tag: | ||||||
|  |     prompt: This will push a git tag and docker image versioned {{.TAG}}... Do you want to continue? | ||||||
|  |     cmds: | ||||||
|  |       - task: build | ||||||
|  |         vars: | ||||||
|  |           NAME: "{{.NAME}}" | ||||||
|  |       - task: push | ||||||
|  |         vars: | ||||||
|  |           NAME: "{{.NAME}}" | ||||||
|  |       - git tag "{{.TAG}}" | ||||||
|  |       - git push origin "{{.TAG}}" | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							|  | @ -1,6 +1,6 @@ | ||||||
| module code.jhot.me/jhot/docker-s3-backup | module code.jhot.me/jhot/docker-s3-backup | ||||||
| 
 | 
 | ||||||
| go 1.20 | go 1.21 | ||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	github.com/go-co-op/gocron v1.33.1 | 	github.com/go-co-op/gocron v1.33.1 | ||||||
|  |  | ||||||
|  | @ -10,29 +10,50 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
| 	MinioClient *minio.Client | 	MinioClient   *minio.Client | ||||||
|  | 	backupBuckets = []string{} | ||||||
|  | 	backupRoot    string | ||||||
|  | 	s3Host        string | ||||||
|  | 	s3Secure      bool | ||||||
|  | 	s3Region      string | ||||||
|  | 	s3User        string | ||||||
|  | 	s3Pass        string | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | func init() { | ||||||
|  | 	for _, bucket := range strings.Split(GetEnvWithDefault("BUCKET_NAMES", ""), ",") { | ||||||
|  | 		backupBuckets = append(backupBuckets, strings.TrimSpace(bucket)) | ||||||
|  | 	} | ||||||
|  | 	backupRoot = GetEnvWithDefault("BACKUP_ROOT", "/backup") | ||||||
|  | 	s3Host = GetEnvWithDefault("S3_HOST", "localhost:9000") | ||||||
|  | 	s3Secure = GetEnvWithDefault("S3_USE_SSL", "") == "true" | ||||||
|  | 	s3Region = GetEnvWithDefault("S3_REGION", "us-east-1") | ||||||
|  | 	s3User = GetEnvWithDefault("S3_ACCESS_KEY_ID", "") | ||||||
|  | 	s3Pass = GetEnvWithDefault("S3_ACCESS_KEY_SECRET", "") | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func Backup(ctx context.Context) error { | func Backup(ctx context.Context) error { | ||||||
|  | 	logger.Info("Starting backup") | ||||||
| 	var err error | 	var err error | ||||||
| 	var getErrors = []string{} | 	var getErrors = []string{} | ||||||
| 	bucketNames := GetEnvWithDefault("BUCKET_NAMES", "") |  | ||||||
| 	backupRoot := GetEnvWithDefault("BACKUP_ROOT", "/backup") |  | ||||||
| 
 | 
 | ||||||
| 	MinioClient, err = minio.New(GetEnvWithDefault("S3_HOST", "localhost"), &minio.Options{ | 	MinioClient, err = minio.New(s3Host, &minio.Options{ | ||||||
| 		Creds:  credentials.NewStaticV4(GetEnvWithDefault("S3_ACCESS_KEY_ID", ""), GetEnvWithDefault("S3_ACCESS_KEY_SECRET", ""), ""), | 		Creds:  credentials.NewStaticV4(s3User, s3Pass, ""), | ||||||
| 		Secure: GetEnvWithDefault("S3_USE_SSL", "") == "true", | 		Secure: s3Secure, | ||||||
| 		Region: GetEnvWithDefault("S3_REGION", "us-east-1"), | 		Region: s3Region, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | 		logger.Error("Error connecting to S3", "error", err) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	logger.Debug("Connected to S3", "host", s3Host) | ||||||
| 
 | 
 | ||||||
| 	for _, bucket := range strings.Split(bucketNames, ",") { | 	for _, bucket := range backupBuckets { | ||||||
| 		bucket = strings.TrimSpace(bucket) | 		logger.Debug("Backing up bucket", "bucket", bucket) | ||||||
| 		for object := range MinioClient.ListObjects(ctx, bucket, minio.ListObjectsOptions{Recursive: true}) { | 		for object := range MinioClient.ListObjects(ctx, bucket, minio.ListObjectsOptions{Recursive: true}) { | ||||||
| 			getError := MinioClient.FGetObject(ctx, bucket, object.Key, fmt.Sprintf("%s/%s/%s", backupRoot, bucket, object.Key), minio.GetObjectOptions{}) | 			getError := MinioClient.FGetObject(ctx, bucket, object.Key, fmt.Sprintf("%s/%s/%s", backupRoot, bucket, object.Key), minio.GetObjectOptions{}) | ||||||
| 			if getError != nil { | 			if getError != nil { | ||||||
|  | 				logger.Error("Error getting object", "bucket", bucket, "error", getError) | ||||||
| 				getErrors = append(getErrors, getError.Error()) | 				getErrors = append(getErrors, getError.Error()) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | package internal | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log/slog" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	logger *slog.Logger | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})) | ||||||
|  | } | ||||||
|  | @ -12,12 +12,14 @@ var ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func StartSchedule(ctx context.Context) error { | func StartSchedule(ctx context.Context) error { | ||||||
|  | 	logger.Info("Starting schedule") | ||||||
| 	cronExpression := GetEnvWithDefault("SCHEDULE_CRON", "0 0 * * *") | 	cronExpression := GetEnvWithDefault("SCHEDULE_CRON", "0 0 * * *") | ||||||
| 	scheduler = gocron.NewScheduler(time.Local) | 	scheduler = gocron.NewScheduler(time.Local) | ||||||
| 	_, err := scheduler.Cron(cronExpression).Do(Backup, ctx) | 	job, err := scheduler.Cron(cronExpression).Do(Backup, ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	logger.Debug("Next scheduled backup", "time", job.NextRun()) | ||||||
| 	scheduler.StartBlocking() | 	scheduler.StartBlocking() | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue