package storage import ( "fmt" "log" "os" ) // Init creates an ObjectStore based on the configuration. // // Auto-detection when backend is empty: // - If storagePath is writable → PVC (implicit) // - If storagePath is missing/unwritable → nil (storage disabled) // // Explicit backends: // - "pvc" → PVC, fail if path is not writable // - "s3" → S3-compatible (MinIO, Ceph RGW, AWS), fail if not reachable func Init(backend, storagePath string, s3Cfg *S3Config) (ObjectStore, error) { switch backend { case "pvc": // Explicit PVC — fail if not writable s, err := NewPVC(storagePath) if err != nil { return nil, fmt.Errorf("storage: PVC backend at %q: %w", storagePath, err) } log.Printf(" 📁 Storage: PVC at %s", storagePath) return s, nil case "s3": if s3Cfg == nil { return nil, fmt.Errorf("storage: S3 backend requires S3_BUCKET and credentials") } s, err := NewS3(*s3Cfg) if err != nil { return nil, fmt.Errorf("storage: S3 backend: %w", err) } endpoint := s3Cfg.Endpoint if endpoint == "" { endpoint = "AWS" } log.Printf(" 📁 Storage: S3 at %s/%s (prefix=%q)", endpoint, s3Cfg.Bucket, s3Cfg.Prefix) return s, nil case "": // Auto-detect: try PVC if path exists or is creatable s, err := NewPVC(storagePath) if err != nil { // Path not writable — storage disabled, not an error log.Printf(" 📁 Storage: disabled (path %s not writable)", storagePath) return nil, nil } log.Printf(" 📁 Storage: PVC at %s (auto-detected)", storagePath) return s, nil default: return nil, fmt.Errorf("storage: unknown backend %q (expected pvc or s3)", backend) } } // IsPathWritable checks if a directory path exists and is writable. // Used by auto-detection. Does not create the directory. func IsPathWritable(path string) bool { info, err := os.Stat(path) if err != nil { return false } if !info.IsDir() { return false } // Try writing a probe file probe := path + "/.writable-probe" if err := os.WriteFile(probe, []byte("ok"), 0o644); err != nil { return false } os.Remove(probe) return true }