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