Skip to content

Commit

Permalink
zed: Default app data location (#4758)
Browse files Browse the repository at this point in the history
If no lake location is specified, zed will use a per-os default
location. Also if the default location is used, zed will first check if
there's a service on 9867 and opt to connect to that instead of
operating locally.
  • Loading branch information
mattnibs authored Oct 10, 2023
1 parent 40a2d27 commit e0f4839
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 33 deletions.
30 changes: 30 additions & 0 deletions cli/lakeflags/datadir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package lakeflags

import (
"os"
"path/filepath"
"runtime"
)

// getDefaultDataDir returns the default data directory for the current user.
// Derived from https://github.com/btcsuite/btcd/blob/master/btcutil/appdata.go
func getDefaultDataDir() string {
// Resolve the XDG data home directory if set.
if xdgDataHome := os.Getenv("XDG_DATA_HOME"); xdgDataHome != "" {
return filepath.Join(xdgDataHome, "zed")
}
if runtime.GOOS == "windows" {
if appData := os.Getenv("LOCALAPPDATA"); appData != "" {
return filepath.Join(appData, "zed")
}
}
if homeDir, _ := os.UserHomeDir(); homeDir != "" {
// Follow the XDG spec which states:
// If $XDG_DATA_HOME is either not set or empty, a default equal to
// $HOME/.local/share should be used.
return filepath.Join(homeDir, ".local", "share", "zed")
}
// Return an empty string which will cause an error if a default data
// directory cannot be found.
return ""
}
47 changes: 33 additions & 14 deletions cli/lakeflags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ var ErrNoHEAD = errors.New("HEAD not specified: indicate with -use or run the \"

type Flags struct {
ConfigDir string
// LakeSpecified is set to true if the lake is explicitly set via either
// command line flag or environment variable.
LakeSpecified bool
Lake string
Quiet bool
Lake string
Quiet bool

lakeSpecified bool
}

func (l *Flags) SetFlags(fs *flag.FlagSet) {
Expand All @@ -35,20 +34,17 @@ func (l *Flags) SetFlags(fs *flag.FlagSet) {
dir = filepath.Join(dir, ".zed")
}
fs.StringVar(&l.ConfigDir, "configdir", dir, "configuration and credentials directory")
l.Lake = "http://localhost:9867"
if s, ok := os.LookupEnv("ZED_LAKE"); ok {
l.Lake = strings.TrimRight(s, "/")
l.LakeSpecified = true
l.Lake, l.lakeSpecified = s, true
}
fs.Func("lake", fmt.Sprintf("lake location (env ZED_LAKE) (default %s)", l.Lake), func(s string) error {
l.Lake = strings.TrimRight(s, "/")
l.LakeSpecified = true
l.Lake, l.lakeSpecified = s, true
return nil
})
}

func (l *Flags) Connection() (*client.Connection, error) {
uri, err := l.URI()
uri, err := l.ClientURI()
if err != nil {
return nil, err
}
Expand All @@ -63,7 +59,7 @@ func (l *Flags) Connection() (*client.Connection, error) {
}

func (l *Flags) Open(ctx context.Context) (api.Interface, error) {
uri, err := l.URI()
uri, err := l.ClientURI()
if err != nil {
return nil, err
}
Expand All @@ -86,12 +82,35 @@ func (l *Flags) AuthStore() *auth0.Store {
}

func (l *Flags) URI() (*storage.URI, error) {
if l.Lake == "" {
lk := strings.TrimRight(l.Lake, "/")
if !l.lakeSpecified {
lk = getDefaultDataDir()
}
if lk == "" {
return nil, errors.New("lake location must be set (either with the -lake flag or ZED_LAKE environment variable)")
}
u, err := storage.ParseURI(l.Lake)
u, err := storage.ParseURI(lk)
if err != nil {
err = fmt.Errorf("error parsing lake location: %w", err)
}
return u, err
}

// ClientURI returns the URI of the lake to connect to. If the lake path is
// the defaultDataDir, it first checks if a zed service is running on
// localhost:9867 and if so uses http://localhost:9867 as the lake location.
func (l *Flags) ClientURI() (*storage.URI, error) {
u, err := l.URI()
if err != nil {
return nil, err
}
if !l.lakeSpecified && localServer() {
u = storage.MustParseURI("http://localhost:9867")
}
return u, nil
}

func localServer() bool {
_, err := client.NewConnection().Ping(context.Background())
return err == nil
}
24 changes: 15 additions & 9 deletions cmd/zed/init/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/brimdata/zed/cmd/zed/root"
"github.com/brimdata/zed/lake/api"
"github.com/brimdata/zed/pkg/charm"
"github.com/brimdata/zed/pkg/storage"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -35,23 +36,28 @@ func (c *Command) Run(args []string) error {
return err
}
defer cleanup()
var path string
var u *storage.URI
if len(args) == 0 {
path = c.LakeFlags.Lake
if u, err = c.LakeFlags.URI(); err != nil {
return err
}
} else if len(args) == 1 {
path = args[0]
path := args[0]
if path == "" {
return errors.New("single lake path argument required")
}
if u, err = storage.ParseURI(path); err != nil {
return err
}
}
if path == "" {
return errors.New("single lake path argument required")
}
if api.IsLakeService(path) {
if api.IsLakeService(u.String()) {
return fmt.Errorf("init command not valid on remote lake")
}
if _, err := api.CreateLocalLake(ctx, zap.Must(zap.NewProduction()), path); err != nil {
if _, err := api.CreateLocalLake(ctx, zap.Must(zap.NewProduction()), u.String()); err != nil {
return err
}
if !c.LakeFlags.Quiet {
fmt.Printf("lake created: %s\n", path)
fmt.Printf("lake created: %s\n", u)
}
return nil
}
9 changes: 2 additions & 7 deletions cmd/zed/serve/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,12 @@ func (c *Command) Run(args []string) error {
return err
}
defer cleanup()
if !c.LakeFlags.LakeSpecified {
c.LakeFlags.Lake = ""
}
uri, err := c.LakeFlags.URI()
if err != nil {
if c.conf.Root, err = c.LakeFlags.URI(); err != nil {
return err
}
if api.IsLakeService(uri.String()) {
if api.IsLakeService(c.conf.Root.String()) {
return errors.New("serve command available for local lakes only")
}
c.conf.Root = uri
if c.rootContentFile != "" {
f, err := fs.Open(c.rootContentFile)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/zed/use/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (c *Command) Run(args []string) error {
return errors.New("default pool and branch unset")
}
fmt.Printf("HEAD at %s\n", head)
if u, err := c.LakeFlags.URI(); err == nil {
if u, err := c.LakeFlags.ClientURI(); err == nil {
fmt.Printf("Lake at %s\n", u)
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion cmd/zed/ztests/no-lake-location.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
script: |
! zed ls -lake ''
! zed serve
! zed serve -lake ''
outputs:
- name: stderr
Expand Down
8 changes: 8 additions & 0 deletions cmd/zed/ztests/xdg-data-home.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
script: |
export XDG_DATA_HOME=path/to/lake
zed init
outputs:
- name: stdout
regexp: |
lake created: file:.*path/to/lake/zed
2 changes: 1 addition & 1 deletion compiler/ztests/from-error.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
script: |
! zc -C -s 'from p'
! zc -lake='' -C -s 'from p'
echo === >&2
export ZED_LAKE=test
zed init
Expand Down

0 comments on commit e0f4839

Please sign in to comment.