repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

pico / cmd / scripts / clean-object-store
Antonio Mika · 08 Oct 24

clean.go

  1package main
  2
  3import (
  4	"log/slog"
  5	"os"
  6	"strings"
  7
  8	"github.com/picosh/pico/db"
  9	"github.com/picosh/pico/db/postgres"
 10	"github.com/picosh/pico/pgs"
 11	"github.com/picosh/pico/shared"
 12	"github.com/picosh/pico/shared/storage"
 13	"github.com/picosh/utils"
 14)
 15
 16func bail(err error) {
 17	if err != nil {
 18		panic(err)
 19	}
 20}
 21
 22type RmProject struct {
 23	user *db.User
 24	name string
 25}
 26
 27// this script will find any objects stored within Store that does not
 28// have a corresponding project inside our database.
 29func main() {
 30	// to actually commit changes, set to true
 31	writeEnv := utils.GetEnv("WRITE", "0")
 32	write := false
 33	if writeEnv == "1" {
 34		write = true
 35	}
 36	logger := slog.Default()
 37
 38	picoCfg := shared.NewConfigSite()
 39	picoCfg.Logger = logger
 40	picoCfg.DbURL = os.Getenv("DATABASE_URL")
 41	picoCfg.MinioURL = os.Getenv("MINIO_URL")
 42	picoCfg.MinioUser = os.Getenv("MINIO_ROOT_USER")
 43	picoCfg.MinioPass = os.Getenv("MINIO_ROOT_PASSWORD")
 44	picoDb := postgres.NewDB(picoCfg.DbURL, picoCfg.Logger)
 45
 46	var st storage.StorageServe
 47	var err error
 48	st, err = storage.NewStorageMinio(picoCfg.MinioURL, picoCfg.MinioUser, picoCfg.MinioPass)
 49	bail(err)
 50
 51	logger.Info("fetching all users")
 52	users, err := picoDb.FindUsers()
 53	bail(err)
 54
 55	logger.Info("fetching all buckets")
 56	buckets, err := st.ListBuckets()
 57	bail(err)
 58
 59	rmProjects := []RmProject{}
 60
 61	for _, bucketName := range buckets {
 62		// only care about pgs
 63		if !strings.HasPrefix(bucketName, "static-") {
 64			continue
 65		}
 66
 67		bucket, err := st.GetBucket(bucketName)
 68		bail(err)
 69		bucketProjects, err := st.ListObjects(bucket, "/", false)
 70		bail(err)
 71
 72		userID := strings.Replace(bucketName, "static-", "", 1)
 73		user := &db.User{
 74			ID:   userID,
 75			Name: userID,
 76		}
 77		for _, u := range users {
 78			if u.ID == userID {
 79				user = u
 80				break
 81			}
 82		}
 83		projects, err := picoDb.FindProjectsByUser(userID)
 84		bail(err)
 85		for _, bucketProject := range bucketProjects {
 86			found := false
 87			for _, project := range projects {
 88				// ignore links
 89				if project.Name != project.ProjectDir {
 90					continue
 91				}
 92				if project.Name == bucketProject.Name() {
 93					found = true
 94				}
 95			}
 96			if !found {
 97				logger.Info("marking for removal", "bucket", bucketName, "project", bucketProject.Name())
 98				rmProjects = append(rmProjects, RmProject{
 99					name: bucketProject.Name(),
100					user: user,
101				})
102			}
103		}
104	}
105
106	session := &utils.CmdSessionLogger{
107		Log: logger,
108	}
109
110	for _, project := range rmProjects {
111		opts := &pgs.Cmd{
112			Session: session,
113			User:    project.user,
114			Store:   st,
115			Log:     logger,
116			Dbpool:  picoDb,
117			Write:   write,
118		}
119		err := opts.RmProjectAssets(project.name)
120		bail(err)
121	}
122
123	logger.Info("store projects marked for deletion", "length", len(rmProjects))
124	for _, project := range rmProjects {
125		logger.Info("removing project", "user", project.user.Name, "project", project.name)
126	}
127	if !write {
128		logger.Info("WARNING: changes not committed, need env var WRITE=1")
129	}
130}