ソースを参照

Changes on params

Moved drive config to be single filed instead of auth.json and
client_secret.json

Added source to params to use like:
	cloudmount source.json targetpath
	if no source is passed it will read from default:
	$HomeDir/.cloudmount/$type.json
luis 7 年 前
コミット
adf4880e51

+ 12 - 4
flags.go

@@ -5,6 +5,7 @@ import (
 	"flag"
 	"fmt"
 	"os"
+	"path/filepath"
 	"strconv"
 	"strings"
 
@@ -14,7 +15,7 @@ import (
 func parseFlags(config *core.Config) (err error) {
 	var mountoptsFlag string
 
-	flag.StringVar(&config.CloudFSDriver, "t", config.CloudFSDriver, "which cloud service to use [gdrive]")
+	flag.StringVar(&config.Type, "t", config.Type, "which cloud service to use [gdrive]")
 	flag.BoolVar(&config.Daemonize, "d", false, "Run app in background")
 	flag.BoolVar(&config.VerboseLog, "v", false, "Verbose log")
 	flag.StringVar(&config.HomeDir, "w", config.HomeDir, "Work dir, path that holds configurations")
@@ -23,18 +24,25 @@ func parseFlags(config *core.Config) (err error) {
 	flag.StringVar(&mountoptsFlag, "o", "", "uid,gid ex: -o uid=1000,gid=0 ")
 
 	flag.Usage = func() {
-		fmt.Fprintf(os.Stderr, "Usage: %s [options] MOUNTPOINT\n\n", os.Args[0])
+		fmt.Fprintf(os.Stderr, "Usage: %s [options] <SRC/CONFIG?> MOUNTPOINT\n\n", os.Args[0])
 		fmt.Fprintf(os.Stderr, "Options:\n")
 		flag.PrintDefaults()
 		fmt.Fprintf(os.Stderr, "\n")
 	}
 	flag.Parse()
 
-	if len(flag.Args()) < 1 {
+	if flag.NArg() < 1 {
 		flag.Usage()
-		//fmt.Println("Usage:\n gdrivemount [-d] [-v] MOUNTPOINT")
+		//fmt.Println("Usage:\n gdrivemount [-d] [-v] <SRC/CONFIG> <MOUNTPOINT>")
 		return errors.New("Missing parameter")
 	}
+	if flag.NArg() == 1 {
+		config.Source = filepath.Join(config.HomeDir, config.Type+".json")
+		config.Target = flag.Arg(0)
+	} else {
+		config.Source = flag.Arg(0)
+		config.Target = flag.Arg(1)
+	}
 	/////////////////////////////////////
 	// Parse mount opts
 	/////////////////

+ 12 - 7
internal/core/config.go

@@ -4,11 +4,16 @@ import "time"
 
 // Config struct
 type Config struct {
-	Daemonize     bool
-	CloudFSDriver string
-	VerboseLog    bool
-	RefreshTime   time.Duration
-	HomeDir       string
-	UID           uint32 // Mount UID
-	GID           uint32 // Mount GID
+	Daemonize   bool
+	Type        string
+	VerboseLog  bool
+	RefreshTime time.Duration
+	HomeDir     string
+	UID         uint32 // Mount UID
+	GID         uint32 // Mount GID
+	Target      string // should be a folder
+	Source      string
+
+	// Driver specific params:
+	Param map[string]interface{}
 }

+ 14 - 10
internal/core/core.go

@@ -3,7 +3,6 @@ package core
 import (
 	"context"
 	"flag"
-	"log"
 	"os"
 	"os/signal"
 	"os/user"
@@ -19,6 +18,10 @@ import (
 	"github.com/jacobsa/fuse/fuseutil"
 )
 
+var (
+	log = prettylog.New("cloudmount")
+)
+
 // Core struct
 type Core struct {
 	Config  Config
@@ -48,13 +51,14 @@ func New() *Core {
 	return &Core{
 		Drivers: map[string]DriverFactory{},
 		Config: Config{
-			Daemonize:     false,
-			CloudFSDriver: "gdrive",
-			VerboseLog:    false,
-			RefreshTime:   2 * time.Minute,
-			HomeDir:       filepath.Join(usr.HomeDir, ".cloudmount"),
-			UID:           uint32(uid),
-			GID:           uint32(gid),
+			Daemonize:   false,
+			Type:        "gdrive",
+			VerboseLog:  false,
+			RefreshTime: 2 * time.Minute,
+			HomeDir:     filepath.Join(usr.HomeDir, ".cloudmount"),
+			Source:      filepath.Join(usr.HomeDir, ".cloudmount", "gdrive.json"),
+			UID:         uint32(uid),
+			GID:         uint32(gid),
 		},
 	}
 
@@ -63,7 +67,7 @@ func New() *Core {
 // Init to be run after configuration
 func (c *Core) Init() (err error) {
 
-	fsFactory, ok := c.Drivers[c.Config.CloudFSDriver]
+	fsFactory, ok := c.Drivers[c.Config.Type]
 	if !ok {
 		log.Fatal("CloudFS not supported")
 	}
@@ -82,7 +86,7 @@ func (c *Core) Mount() {
 	/////////
 	ctx := context.Background()
 	server := fuseutil.NewFileSystemServer(c.CurrentFS)
-	mountPath := flag.Arg(0)
+	mountPath := c.Config.Target
 
 	var err error
 	var mfs *fuse.MountedFileSystem

+ 37 - 0
internal/core/util.go

@@ -0,0 +1,37 @@
+package core
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"strings"
+
+	"github.com/go-yaml/yaml"
+)
+
+// Some utils
+func ParseConfig(srcfile string, out interface{}) (err error) {
+	if srcfile == "" {
+		return
+	}
+	f, err := os.Open(srcfile)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	if strings.HasSuffix(srcfile, ".json") {
+		// Read as JSON
+		json.NewDecoder(f).Decode(out)
+		return
+	}
+	if strings.HasSuffix(srcfile, ".yaml") {
+		data, err := ioutil.ReadAll(f)
+		if err != nil {
+			return err
+		}
+		// Read as yaml
+		yaml.Unmarshal(data, out)
+	}
+	return err
+}

+ 89 - 34
internal/fs/gdrivefs/client.go

@@ -6,43 +6,63 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
-	"net/http"
-	"net/url"
 	"os"
-	"path/filepath"
 
 	drive "google.golang.org/api/drive/v3"
 
+	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
+
 	"golang.org/x/oauth2"
-	"golang.org/x/oauth2/google"
 )
 
-func (d *GDriveFS) getClient(ctx context.Context, config *oauth2.Config) *http.Client {
-	cacheFile, err := d.tokenCacheFile()
-	if err != nil {
-		log.Fatalf("Unable to get path to cached credential file. %v", err)
-	}
+type ServiceConfig struct {
+	ClientSecret struct {
+		ClientID     string   `json:"client_id"`
+		ClientSecret string   `json:"client_secret"`
+		RedirectURIs []string `json:"redirect_uris"`
+		AuthURI      string   `json:"auth_uri"`
+		TokenURI     string   `json:"token_uri"`
+	} `json:"client_secret"`
+
+	Auth *oauth2.Token `json:"auth"`
+	/*struct {
+		AccessToken  string `json:"access_token"`
+		TokenType    string `json:"token_type"`
+		RefreshToken string `json:"refresh_token"`
+		Expiry       string `json:"Expiry"`
+	} `json:"auth"`*/
+}
 
-	tok, err := d.tokenFromFile(cacheFile)
-	if err != nil {
-		tok = d.getTokenFromWeb(config)
-		d.saveToken(cacheFile, tok)
+//func (d *GDriveFS) getClient(ctx context.Context, config *oauth2.Config) *http.Client {
+//	cacheFile, err := d.tokenCacheFile()
+//	if err != nil {
+///		log.Fatalf("Unable to get path to cached credential file. %v", err)
+//	}
+
+/*if d.serviceConfig.Auth.AccessToken == "" {
+		tok := getTokenFromWeb(config)
+		d.serviceConfig.Auth = tok
+		d.saveToken() // Save config actually
 	}
+	//tok, err := d.tokenFromFile(cacheFile)
+	//if err != nil {
+	//	tok = d.getTokenFromWeb(config)
+	//	d.saveToken(cacheFile, tok)
+	//	}
 	return config.Client(ctx, tok)
 
-}
+//}
 
-func (d *GDriveFS) tokenCacheFile() (string, error) {
+/*func (d *GDriveFS) tokenCacheFile() (string, error) {
 	tokenCacheDir := d.config.HomeDir
 
 	err := os.MkdirAll(tokenCacheDir, 0700)
 
 	return filepath.Join(tokenCacheDir, url.QueryEscape("auth.json")), err
 
-}
+}*/
 
-func (d *GDriveFS) getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
+func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
 	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
 
 	fmt.Printf(
@@ -66,7 +86,7 @@ type the authorization code: `, authURL)
 	return tok
 }
 
-func (d *GDriveFS) tokenFromFile(file string) (*oauth2.Token, error) {
+/*func (d *GDriveFS) tokenFromFile(file string) (*oauth2.Token, error) {
 	f, err := os.Open(file)
 	if err != nil {
 		return nil, err
@@ -76,10 +96,13 @@ func (d *GDriveFS) tokenFromFile(file string) (*oauth2.Token, error) {
 	t := &oauth2.Token{}
 	err = json.NewDecoder(f).Decode(t)
 	return t, err
-}
+}*/
+
+//func (d *GDriveFS) saveToken(file string, token *oauth2.Token) {
+/*func (d *GDriveFS) saveToken() { // Save credentials
 
-func (d *GDriveFS) saveToken(file string, token *oauth2.Token) {
-	log.Printf("Saving credential file to: %s\n", file)
+	// Save token in SOURCE FILE
+	log.Printf("Saving credential file to: %s\n", d.config.Source)
 	f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
 	if err != nil {
 		log.Fatalf("Unable to cache oauth token: %v\n", err)
@@ -87,36 +110,68 @@ func (d *GDriveFS) saveToken(file string, token *oauth2.Token) {
 	defer f.Close()
 
 	json.NewEncoder(f).Encode(token)
-}
+}*/
+
+func (d *GDriveFS) saveConfig() {
 
-/*func getConfigPath() (string, error) {
-	usr, err := user.Current()
+	data, err := json.MarshalIndent(d.serviceConfig, "  ", "  ")
 	if err != nil {
-		return "", err
+		panic(err)
 	}
-	configDir := filepath.Join(usr.HomeDir, ".gdrivemount")
 
-	return configDir, nil
-}*/
+	f, err := os.OpenFile(d.config.Source, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		log.Fatalf("Unable to cache oauth token: %v\n", err)
+	}
+	defer f.Close()
+
+	f.Write(data)
+	f.Sync()
+
+}
 
 // Init driveService
 func (d *GDriveFS) initClient() {
 
-	configPath := d.config.HomeDir
+	//configPath := d.config.HomeDir
 
 	ctx := context.Background() // Context from GDriveFS
 
-	b, err := ioutil.ReadFile(filepath.Join(configPath, "client_secret.json"))
+	log.Println("Initializing gdrive service")
+	log.Println("Source config:", d.config.Source)
+
+	err := core.ParseConfig(d.config.Source, d.serviceConfig)
+
+	//b, err := ioutil.ReadFile(d.config.Source)
+
+	//b, err := ioutil.ReadFile(filepath.Join(configPath, "client_secret.json"))
 	if err != nil {
 		log.Fatalf("Unable to read client secret file: %v", err)
 	}
+	config := &oauth2.Config{
+		ClientID:     d.serviceConfig.ClientSecret.ClientID,
+		ClientSecret: d.serviceConfig.ClientSecret.ClientSecret,
+		RedirectURL:  d.serviceConfig.ClientSecret.RedirectURIs[0],
+		Scopes:       []string{drive.DriveScope},
+		Endpoint: oauth2.Endpoint{
+			AuthURL:  d.serviceConfig.ClientSecret.AuthURI,
+			TokenURL: d.serviceConfig.ClientSecret.TokenURI,
+		},
+	}
+	// We can deal with oauthToken here too
 
-	config, err := google.ConfigFromJSON(b, drive.DriveScope)
+	if d.serviceConfig.Auth == nil {
+		tok := getTokenFromWeb(config)
+		d.serviceConfig.Auth = tok
+		d.saveConfig()
+	}
+
+	/*config, err := google.ConfigFromJSON(b, drive.DriveScope)
 	if err != nil {
 		log.Fatalf("Unable to parse client secret file: %v", err)
-	}
+	}*/
 
-	client := d.getClient(ctx, config)
+	client := config.Client(ctx, d.serviceConfig.Auth)
 	d.client, err = drive.New(client)
 	if err != nil {
 		log.Fatalf("Unable to retrieve drive Client: %v", err)

+ 7 - 5
internal/fs/gdrivefs/gdrivefs.go

@@ -37,8 +37,9 @@ type Handle struct {
 type GDriveFS struct {
 	fuseutil.NotImplementedFileSystem // Defaults
 
-	config *core.Config //core   *core.Core // Core Config instead?
-	client *drive.Service
+	config        *core.Config //core   *core.Core // Core Config instead?
+	serviceConfig *ServiceConfig
+	client        *drive.Service
 	//root   *FileEntry // hiearchy reference
 	root *FileContainer
 
@@ -55,9 +56,10 @@ type GDriveFS struct {
 func New(core *core.Core) core.Driver {
 
 	fs := &GDriveFS{
-		config:      &core.Config,
-		fileHandles: map[fuseops.HandleID]*Handle{},
-		handleMU:    &sync.Mutex{},
+		config:        &core.Config,
+		serviceConfig: &ServiceConfig{},
+		fileHandles:   map[fuseops.HandleID]*Handle{},
+		handleMU:      &sync.Mutex{},
 	}
 	fs.initClient() // Init Oauth2 client
 	fs.root = NewFileContainer(fs)