diff --git a/.gitignore b/.gitignore index a072fb2..e24a5db 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ go.work.sum # .vscode/ ironmount out/ +*.db diff --git a/docker-compose.yml b/docker-compose.yml index cdf2d96..a72317c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,7 @@ services: restart: unless-stopped volumes: - ./:/ironmount - - /run/docker/plugins:/run/docker/plugins - - /tmp/ironmount:/tmp/ironmount + - ./tmp:/tmp/ironmount environment: - GO_ENV=development diff --git a/go.mod b/go.mod index 6a0c940..405a13d 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,17 @@ module ironmount go 1.24.5 + +require ( + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect + golang.org/x/sys v0.34.0 // indirect + modernc.org/libc v1.66.3 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect + modernc.org/sqlite v1.38.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..057de1d --- /dev/null +++ b/go.sum @@ -0,0 +1,23 @@ +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= +modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= +modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= diff --git a/internal/constants/constants.go b/internal/constants/constants.go index dba264a..377dfec 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -1,3 +1,3 @@ package constants -var VolumeRoot = "/tmp/ironmount" +var VolumeRoot = "/home/nicolas/ironmount/tmp" diff --git a/internal/db/db.go b/internal/db/db.go new file mode 100644 index 0000000..20c2b80 --- /dev/null +++ b/internal/db/db.go @@ -0,0 +1,92 @@ +package db + +import ( + "database/sql" + "log" + + _ "modernc.org/sqlite" +) + +type Volume struct { + Name string `json:"name"` + Path string `json:"path"` +} + +// DB is the global database connection +var DB, err = sql.Open("sqlite", "file:ironmount.db") + +// Init initializes the database and creates the volumes table if it doesn't exist +func Init() { + if err != nil { + panic(err) + } + + _, err = DB.Exec(` + CREATE TABLE IF NOT EXISTS volumes ( + name TEXT PRIMARY KEY, + path TEXT NOT NULL + ); + `) + if err != nil { + panic(err) + } +} + +func GetVolumeByName(n string) (*Volume, error) { + var path string + var name string + + err := DB.QueryRow("SELECT name, path FROM volumes WHERE name = ?", n).Scan(&name, &path) + + if err != nil { + return nil, err + } + + return &Volume{ + Name: name, + Path: path, + }, nil +} + +func CreateVolume(name, path string) error { + _, err := DB.Exec("INSERT INTO volumes (name, path) VALUES (?, ?)", name, path) + if err != nil { + return err + } + return nil +} + +func RemoveVolume(name string) error { + _, err := DB.Exec("DELETE FROM volumes WHERE name = ?", name) + + log.Printf("Removing volume: %s", name) + log.Printf("Error removing volume: %v", err) + + if err != nil { + return err + } + return nil +} + +func ListVolumes() ([]Volume, error) { + rows, err := DB.Query("SELECT name, path FROM volumes") + if err != nil { + return nil, err + } + defer rows.Close() + + var volumes []Volume + for rows.Next() { + var vol Volume + if err := rows.Scan(&vol.Name, &vol.Path); err != nil { + return nil, err + } + volumes = append(volumes, vol) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return volumes, nil +} diff --git a/internal/driver/create.go b/internal/driver/create.go index 7e46492..cca41ab 100644 --- a/internal/driver/create.go +++ b/internal/driver/create.go @@ -3,6 +3,7 @@ package driver import ( "encoding/json" "ironmount/internal/constants" + "ironmount/internal/db" "log" "net/http" "os" @@ -24,12 +25,13 @@ func Create(w http.ResponseWriter, r *http.Request) { return } + db.CreateVolume(req.Name, volPath) + response := map[string]string{ "Name": req.Name, "Mountpoint": volPath, "Err": "", } - volumes[req.Name] = Volume{Name: req.Name, Path: volPath} _ = json.NewEncoder(w).Encode(response) } diff --git a/internal/driver/get.go b/internal/driver/get.go index 725f27d..63aaaf3 100644 --- a/internal/driver/get.go +++ b/internal/driver/get.go @@ -2,6 +2,7 @@ package driver import ( "encoding/json" + "ironmount/internal/db" "log" "net/http" ) @@ -14,7 +15,18 @@ func Get(w http.ResponseWriter, r *http.Request) { } _ = json.NewDecoder(r.Body).Decode(&req) - vol := volumes[req.Name] + vol, err := db.GetVolumeByName(req.Name) + + if err != nil { + log.Printf("Error retrieving volume: %s", err.Error()) + + response := map[string]string{ + "Err": err.Error(), + } + _ = json.NewEncoder(w).Encode(response) + + return + } response := map[string]any{ "Volume": map[string]any{ diff --git a/internal/driver/list.go b/internal/driver/list.go index 0523ba4..f1e0a86 100644 --- a/internal/driver/list.go +++ b/internal/driver/list.go @@ -2,6 +2,7 @@ package driver import ( "encoding/json" + "ironmount/internal/db" "log" "net/http" ) @@ -9,14 +10,18 @@ import ( func List(w http.ResponseWriter, r *http.Request) { log.Printf("Received list request: %s", r.URL.Path) - var vols []map[string]string - for _, v := range volumes { - vols = append(vols, map[string]string{ - "Name": v.Name, + volumes, err := db.ListVolumes() + if err != nil { + log.Printf("Error listing volumes: %s", err.Error()) + json.NewEncoder(w).Encode(map[string]any{ + "Volumes": nil, + "Err": err.Error(), }) + return } - json.NewEncoder(w).Encode(map[string]interface{}{ - "Volumes": vols, + + json.NewEncoder(w).Encode(map[string]any{ + "Volumes": volumes, "Err": "", }) } diff --git a/internal/driver/mount.go b/internal/driver/mount.go index 760d2ec..63b6b73 100644 --- a/internal/driver/mount.go +++ b/internal/driver/mount.go @@ -2,6 +2,7 @@ package driver import ( "encoding/json" + "ironmount/internal/db" "log" "net/http" ) @@ -17,9 +18,12 @@ func Mount(w http.ResponseWriter, r *http.Request) { return } - vol, ok := volumes[req.Name] - if !ok { - _ = json.NewEncoder(w).Encode(map[string]string{"Err": "volume not found"}) + vol, err := db.GetVolumeByName(req.Name) + if err != nil { + log.Printf("Error retrieving volume: %s", err.Error()) + _ = json.NewEncoder(w).Encode(map[string]string{ + "Err": err.Error(), + }) return } diff --git a/internal/driver/path.go b/internal/driver/path.go index 8b48540..1eef575 100644 --- a/internal/driver/path.go +++ b/internal/driver/path.go @@ -2,6 +2,7 @@ package driver import ( "encoding/json" + "ironmount/internal/db" "log" "net/http" ) @@ -12,9 +13,11 @@ func Path(w http.ResponseWriter, r *http.Request) { var req PathRequest _ = json.NewDecoder(r.Body).Decode(&req) - vol, ok := volumes[req.Name] - if !ok { - _ = json.NewEncoder(w).Encode(map[string]string{"Err": "volume not found"}) + vol, err := db.GetVolumeByName(req.Name) + if err != nil { + _ = json.NewEncoder(w).Encode(map[string]string{ + "Err": err.Error(), + }) return } diff --git a/internal/driver/remove.go b/internal/driver/remove.go index 86da487..9d39b82 100644 --- a/internal/driver/remove.go +++ b/internal/driver/remove.go @@ -2,8 +2,10 @@ package driver import ( "encoding/json" + "ironmount/internal/db" "log" "net/http" + "os" ) func Remove(w http.ResponseWriter, r *http.Request) { @@ -12,6 +14,17 @@ func Remove(w http.ResponseWriter, r *http.Request) { var req RemoveRequest _ = json.NewDecoder(r.Body).Decode(&req) - delete(volumes, req.Name) + vol, err := db.GetVolumeByName(req.Name) + if err != nil { + log.Printf("Error retrieving volume: %s", err.Error()) + _ = json.NewEncoder(w).Encode(map[string]string{ + "Err": err.Error(), + }) + return + } + + db.RemoveVolume(vol.Name) + os.RemoveAll(vol.Path) + _ = json.NewEncoder(w).Encode(map[string]string{"Err": ""}) } diff --git a/internal/driver/state.go b/internal/driver/state.go deleted file mode 100644 index a07cc5d..0000000 --- a/internal/driver/state.go +++ /dev/null @@ -1,8 +0,0 @@ -package driver - -type Volume struct { - Name string - Path string -} - -var volumes = map[string]Volume{} diff --git a/main.go b/main.go index b887f56..6dc19df 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "ironmount/internal/db" "ironmount/internal/driver" "log" "net" @@ -18,6 +19,8 @@ type Volume struct { var volumes = map[string]Volume{} func main() { + db.Init() + if err := os.MkdirAll("/run/docker/plugins", 0755); err != nil { log.Fatalf("Failed to create plugin directory: %v", err) }