Skip to content

Commit

Permalink
feat: attempt to fix invalid ~/.airbyte permissions (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
colesnodgrass authored Jul 24, 2024
1 parent 7cb08d9 commit a52f0a6
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 6 deletions.
16 changes: 12 additions & 4 deletions internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (

// Help messages to display for specific error situations.
const (
// helpAirbyteDir is display if ErrAirbyteDir is ever returned
helpAirbyteDir = `The ~/.airbyte directory is inaccessible.
You may need to remove this directory before trying your command again.`

// helpDocker is displayed if ErrDocker is ever returned
helpDocker = `An error occurred while communicating with the Docker daemon.
Ensure that Docker is running and is accessible. You may need to upgrade to a newer version of Docker.
Expand Down Expand Up @@ -41,16 +45,20 @@ func Execute(ctx context.Context, cmd *cobra.Command) {
if err := cmd.ExecuteContext(ctx); err != nil {
pterm.Error.Println(err)

if errors.Is(err, localerr.ErrDocker) {
switch {
case errors.Is(err, localerr.ErrAirbyteDir):
pterm.Println()
pterm.Info.Println(helpAirbyteDir)
case errors.Is(err, localerr.ErrDocker):
pterm.Println()
pterm.Info.Println(helpDocker)
} else if errors.Is(err, localerr.ErrKubernetes) {
case errors.Is(err, localerr.ErrKubernetes):
pterm.Println()
pterm.Info.Println(helpKubernetes)
} else if errors.Is(err, localerr.ErrIngress) {
case errors.Is(err, localerr.ErrIngress):
pterm.Println()
pterm.Info.Println(helpIngress)
} else if errors.Is(err, localerr.ErrPort) {
case errors.Is(err, localerr.ErrPort):
pterm.Println()
pterm.Info.Printfln(helpPort)
}
Expand Down
47 changes: 46 additions & 1 deletion internal/cmd/local/local.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package local

import (
"errors"
"fmt"
"github.com/airbytehq/abctl/internal/cmd/local/k8s"
"github.com/airbytehq/abctl/internal/cmd/local/localerr"
"github.com/airbytehq/abctl/internal/cmd/local/paths"
"github.com/airbytehq/abctl/internal/telemetry"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
"io/fs"
"os"
)

var telClient telemetry.Client
Expand All @@ -14,6 +20,10 @@ func NewCmdLocal(provider k8s.Provider) *cobra.Command {
cmd := &cobra.Command{
Use: "local",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
if err := checkAirbyteDir(); err != nil {
return fmt.Errorf("%w: %w", localerr.ErrAirbyteDir, err)
}

// telemetry client configuration
{
var telOpts []telemetry.GetOption
Expand All @@ -39,5 +49,40 @@ func NewCmdLocal(provider k8s.Provider) *cobra.Command {
}

func printProviderDetails(p k8s.Provider) {
pterm.Info.Printfln("Using Kubernetes provider:\n Provider: %s\n Kubeconfig: %s\n Context: %s", p.Name, p.Kubeconfig, p.Context)
pterm.Info.Println(fmt.Sprintf(
"Using Kubernetes provider:\n Provider: %s\n Kubeconfig: %s\n Context: %s",
p.Name, p.Kubeconfig, p.Context,
))
}

// checkAirbyteDir verifies that, if the paths.Airbyte directory exists, that it has proper permissions.
// If the directory does not have the proper permissions, this method will attempt to fix them.
// A nil response either indicates that either:
// - no paths.Airbyte directory exists
// - the permissions are already correct
// - this function was able to fix the incorrect permissions.
func checkAirbyteDir() error {
fileInfo, err := os.Stat(paths.Airbyte)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// nothing to do, directory will be created later on
return nil
}
return fmt.Errorf("unable to determine status of '%s': %w", paths.Airbyte, err)
}

if !fileInfo.IsDir() {
return errors.New(paths.Airbyte + " is not a directory")
}

if fileInfo.Mode().Perm() >= 0744 {
// directory has minimal permissions
return nil
}

if err := os.Chmod(paths.Airbyte, 0744); err != nil {
return fmt.Errorf("unable to change permissions of '%s': %w", paths.Airbyte, err)
}

return nil
}
9 changes: 8 additions & 1 deletion internal/cmd/local/local/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,14 @@ func (c *Command) handleChart(

c.tel.Attr(fmt.Sprintf("helm_%s_chart_version", req.name), helmChart.Metadata.Version)

c.spinner.UpdateText(fmt.Sprintf("Installing '%s' (version: %s) Helm Chart (this may take several minutes)", req.chartName, helmChart.Metadata.Version))
pterm.Info.Println(fmt.Sprintf(
"Starting Helm Chart installation of '%s' (version: %s)",
req.chartName, helmChart.Metadata.Version,
))
c.spinner.UpdateText(fmt.Sprintf(
"Installing '%s' (version: %s) Helm Chart (this may take several minutes)",
req.chartName, helmChart.Metadata.Version,
))
helmRelease, err := c.helm.InstallOrUpgradeChart(ctx, &helmclient.ChartSpec{
ReleaseName: req.chartRelease,
ChartName: req.chartName,
Expand Down
90 changes: 90 additions & 0 deletions internal/cmd/local/local_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package local

import (
"github.com/airbytehq/abctl/internal/cmd/local/paths"
"github.com/google/go-cmp/cmp"
"os"
"path/filepath"
"testing"
)

func TestCheckAirbyteDir(t *testing.T) {
origDir := paths.Airbyte
t.Cleanup(func() {
paths.Airbyte = origDir
})

t.Run("no directory", func(t *testing.T) {
paths.Airbyte = filepath.Join(t.TempDir(), "does-not-exist")
if err := checkAirbyteDir(); err != nil {
t.Error("unexpected error", err)
}
})

t.Run("directory with correct permissions", func(t *testing.T) {
paths.Airbyte = filepath.Join(t.TempDir(), "correct-perms")
if err := os.MkdirAll(paths.Airbyte, 0744); err != nil {
t.Fatal("unable to create test directory", err)
}
if err := os.Chmod(paths.Airbyte, 0744); err != nil {
t.Fatal("unable to change permissions", err)
}
if err := checkAirbyteDir(); err != nil {
t.Error("unexpected error", err)
}

// permissions should be unchanged
perms, err := os.Stat(paths.Airbyte)
if err != nil {
t.Fatal("unable to check permissions", err)
}
if d := cmp.Diff(0744, int(perms.Mode().Perm())); d != "" {
t.Errorf("permissions mismatch (-want +got):\n%s", d)
}
})

t.Run("directory with higher permissions", func(t *testing.T) {
paths.Airbyte = filepath.Join(t.TempDir(), "correct-perms")
if err := os.MkdirAll(paths.Airbyte, 0777); err != nil {
t.Fatal("unable to create test directory", err)
}
if err := os.Chmod(paths.Airbyte, 0777); err != nil {
t.Fatal("unable to change permissions", err)
}
if err := checkAirbyteDir(); err != nil {
t.Error("unexpected error", err)
}

// permissions should be unchanged
perms, err := os.Stat(paths.Airbyte)
if err != nil {
t.Fatal("unable to check permissions", err)
}
if d := cmp.Diff(0777, int(perms.Mode().Perm())); d != "" {
t.Errorf("permissions mismatch (-want +got):\n%s", d)
}
})

t.Run("directory with incorrect permissions", func(t *testing.T) {
paths.Airbyte = filepath.Join(t.TempDir(), "incorrect-perms")
if err := os.MkdirAll(paths.Airbyte, 0200); err != nil {
t.Fatal("unable to create test directory", err)
}
if err := os.Chmod(paths.Airbyte, 0200); err != nil {
t.Fatal("unable to change permissions", err)
}
// although the permissions are incorrect, checkAirbyteDir should fix them
if err := checkAirbyteDir(); err != nil {
t.Fatal("unexpected error", err)
}

// permissions should be changed
perms, err := os.Stat(paths.Airbyte)
if err != nil {
t.Fatal("unable to check permissions", err)
}
if d := cmp.Diff(0744, int(perms.Mode().Perm())); d != "" {
t.Errorf("permissions mismatch (-want +got):\n%s", d)
}
})
}
3 changes: 3 additions & 0 deletions internal/cmd/local/localerr/localerr.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package localerr
import "errors"

var (
// ErrAirbyteDir is returned anytime an there is an issue in accessing the paths.Airbyte directory.
ErrAirbyteDir = errors.New("airbyte directory is inaccessible")

// ErrDocker is returned anytime an error occurs when attempting to communicate with docker.
ErrDocker = errors.New("error communicating with docker")

Expand Down

0 comments on commit a52f0a6

Please sign in to comment.