mirror of https://github.com/databricks/cli.git
Allow equivalence checking of filer errors to fs errors (#416)
## Changes The pattern `errors.Is(err, fs.ErrNotExist)` is common to check for an error type. Errors can implement `Is(error) bool` with a custom equivalence checker. ## Tests New asserts all pass in the integration test.
This commit is contained in:
parent
42cd8daee0
commit
349e2aff40
|
@ -2,14 +2,15 @@ package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/databricks/cli/bundle"
|
"github.com/databricks/cli/bundle"
|
||||||
"github.com/databricks/cli/libs/filer"
|
"github.com/databricks/cli/libs/filer"
|
||||||
"github.com/databricks/cli/libs/log"
|
"github.com/databricks/cli/libs/log"
|
||||||
"github.com/databricks/databricks-sdk-go/apierr"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type statePull struct{}
|
type statePull struct{}
|
||||||
|
@ -34,7 +35,7 @@ func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
remote, err := f.Read(ctx, TerraformStateFileName)
|
remote, err := f.Read(ctx, TerraformStateFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// On first deploy this state file doesn't yet exist.
|
// On first deploy this state file doesn't yet exist.
|
||||||
if apierr.IsMissing(err) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
log.Infof(ctx, "Remote state file does not exist")
|
log.Infof(ctx, "Remote state file does not exist")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,12 @@ func runFilerReadWriteTest(t *testing.T, ctx context.Context, f filer.Filer) {
|
||||||
// Write should fail because the root path doesn't yet exist.
|
// Write should fail because the root path doesn't yet exist.
|
||||||
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello world`))
|
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello world`))
|
||||||
assert.True(t, errors.As(err, &filer.NoSuchDirectoryError{}))
|
assert.True(t, errors.As(err, &filer.NoSuchDirectoryError{}))
|
||||||
|
assert.True(t, errors.Is(err, fs.ErrNotExist))
|
||||||
|
|
||||||
// Read should fail because the root path doesn't yet exist.
|
// Read should fail because the root path doesn't yet exist.
|
||||||
_, err = f.Read(ctx, "/foo/bar")
|
_, err = f.Read(ctx, "/foo/bar")
|
||||||
assert.True(t, errors.As(err, &filer.FileDoesNotExistError{}))
|
assert.True(t, errors.As(err, &filer.FileDoesNotExistError{}))
|
||||||
|
assert.True(t, errors.Is(err, fs.ErrNotExist))
|
||||||
|
|
||||||
// Write with CreateParentDirectories flag should succeed.
|
// Write with CreateParentDirectories flag should succeed.
|
||||||
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello world`), filer.CreateParentDirectories)
|
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello world`), filer.CreateParentDirectories)
|
||||||
|
@ -59,6 +61,7 @@ func runFilerReadWriteTest(t *testing.T, ctx context.Context, f filer.Filer) {
|
||||||
// Write should fail because there is an existing file at the specified path.
|
// Write should fail because there is an existing file at the specified path.
|
||||||
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello universe`))
|
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello universe`))
|
||||||
assert.True(t, errors.As(err, &filer.FileAlreadyExistsError{}))
|
assert.True(t, errors.As(err, &filer.FileAlreadyExistsError{}))
|
||||||
|
assert.True(t, errors.Is(err, fs.ErrExist))
|
||||||
|
|
||||||
// Write with OverwriteIfExists should succeed.
|
// Write with OverwriteIfExists should succeed.
|
||||||
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello universe`), filer.OverwriteIfExists)
|
err = f.Write(ctx, "/foo/bar", strings.NewReader(`hello universe`), filer.OverwriteIfExists)
|
||||||
|
@ -68,6 +71,7 @@ func runFilerReadWriteTest(t *testing.T, ctx context.Context, f filer.Filer) {
|
||||||
// Delete should fail if the file doesn't exist.
|
// Delete should fail if the file doesn't exist.
|
||||||
err = f.Delete(ctx, "/doesnt_exist")
|
err = f.Delete(ctx, "/doesnt_exist")
|
||||||
assert.True(t, errors.As(err, &filer.FileDoesNotExistError{}))
|
assert.True(t, errors.As(err, &filer.FileDoesNotExistError{}))
|
||||||
|
assert.True(t, errors.Is(err, fs.ErrNotExist))
|
||||||
|
|
||||||
// Delete should succeed for file that does exist.
|
// Delete should succeed for file that does exist.
|
||||||
err = f.Delete(ctx, "/foo/bar")
|
err = f.Delete(ctx, "/foo/bar")
|
||||||
|
@ -102,6 +106,7 @@ func runFilerReadDirTest(t *testing.T, ctx context.Context, f filer.Filer) {
|
||||||
// Expect an error if the path doesn't exist.
|
// Expect an error if the path doesn't exist.
|
||||||
_, err = f.ReadDir(ctx, "/dir/a/b/c/d/e")
|
_, err = f.ReadDir(ctx, "/dir/a/b/c/d/e")
|
||||||
assert.True(t, errors.As(err, &filer.NoSuchDirectoryError{}), err)
|
assert.True(t, errors.As(err, &filer.NoSuchDirectoryError{}), err)
|
||||||
|
assert.True(t, errors.Is(err, fs.ErrNotExist))
|
||||||
|
|
||||||
// Expect two entries in the root.
|
// Expect two entries in the root.
|
||||||
entries, err = f.ReadDir(ctx, ".")
|
entries, err = f.ReadDir(ctx, ".")
|
||||||
|
|
|
@ -22,10 +22,18 @@ func (err FileAlreadyExistsError) Error() string {
|
||||||
return fmt.Sprintf("file already exists: %s", err.path)
|
return fmt.Sprintf("file already exists: %s", err.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (err FileAlreadyExistsError) Is(other error) bool {
|
||||||
|
return other == fs.ErrExist
|
||||||
|
}
|
||||||
|
|
||||||
type FileDoesNotExistError struct {
|
type FileDoesNotExistError struct {
|
||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (err FileDoesNotExistError) Is(other error) bool {
|
||||||
|
return other == fs.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
func (err FileDoesNotExistError) Error() string {
|
func (err FileDoesNotExistError) Error() string {
|
||||||
return fmt.Sprintf("file does not exist: %s", err.path)
|
return fmt.Sprintf("file does not exist: %s", err.path)
|
||||||
}
|
}
|
||||||
|
@ -38,6 +46,10 @@ func (err NoSuchDirectoryError) Error() string {
|
||||||
return fmt.Sprintf("no such directory: %s", err.path)
|
return fmt.Sprintf("no such directory: %s", err.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (err NoSuchDirectoryError) Is(other error) bool {
|
||||||
|
return other == fs.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
// Filer is used to access files in a workspace.
|
// Filer is used to access files in a workspace.
|
||||||
// It has implementations for accessing files in WSFS and in DBFS.
|
// It has implementations for accessing files in WSFS and in DBFS.
|
||||||
type Filer interface {
|
type Filer interface {
|
||||||
|
|
Loading…
Reference in New Issue