forked from GoogleCloudPlatform/nodejs-docs-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for FUSE (GoogleCloudPlatform#135)
* feat: add support for FUSE This is a port of GoogleCloudPlatform/cloud-sql-proxy#1381 and GoogleCloudPlatform/cloud-sql-proxy#1400. Fixes GoogleCloudPlatform#132
- Loading branch information
Showing
18 changed files
with
1,056 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package cmd | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func TestNewCommandArgumentsOnLinux(t *testing.T) { | ||
defaultTmp := filepath.Join(os.TempDir(), "csql-tmp") | ||
tcs := []struct { | ||
desc string | ||
args []string | ||
wantDir string | ||
wantTempDir string | ||
}{ | ||
{ | ||
desc: "using the fuse flag", | ||
args: []string{"--fuse", "/cloudsql"}, | ||
wantDir: "/cloudsql", | ||
wantTempDir: defaultTmp, | ||
}, | ||
{ | ||
desc: "using the fuse temporary directory flag", | ||
args: []string{"--fuse", "/cloudsql", "--fuse-tmp-dir", "/mycooldir"}, | ||
wantDir: "/cloudsql", | ||
wantTempDir: "/mycooldir", | ||
}, | ||
} | ||
|
||
for _, tc := range tcs { | ||
t.Run(tc.desc, func(t *testing.T) { | ||
c := NewCommand() | ||
// Keep the test output quiet | ||
c.SilenceUsage = true | ||
c.SilenceErrors = true | ||
// Disable execute behavior | ||
c.RunE = func(*cobra.Command, []string) error { | ||
return nil | ||
} | ||
c.SetArgs(tc.args) | ||
|
||
err := c.Execute() | ||
if err != nil { | ||
t.Fatalf("want error = nil, got = %v", err) | ||
} | ||
|
||
if got, want := c.conf.FUSEDir, tc.wantDir; got != want { | ||
t.Fatalf("FUSEDir: want = %v, got = %v", want, got) | ||
} | ||
|
||
if got, want := c.conf.FUSETempDir, tc.wantTempDir; got != want { | ||
t.Fatalf("FUSEDir: want = %v, got = %v", want, got) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package cmd | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func TestWindowsDoesNotSupportFUSE(t *testing.T) { | ||
c := NewCommand() | ||
// Keep the test output quiet | ||
c.SilenceUsage = true | ||
c.SilenceErrors = true | ||
// Disable execute behavior | ||
c.RunE = func(*cobra.Command, []string) error { return nil } | ||
c.SetArgs([]string{"--fuse"}) | ||
|
||
err := c.Execute() | ||
if err == nil { | ||
t.Fatal("want error != nil, got = nil") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//go:build !windows | ||
// +build !windows | ||
|
||
package proxy | ||
|
||
import ( | ||
"context" | ||
"syscall" | ||
|
||
"github.com/hanwen/go-fuse/v2/fs" | ||
"github.com/hanwen/go-fuse/v2/fuse" | ||
"github.com/hanwen/go-fuse/v2/fuse/nodefs" | ||
) | ||
|
||
// symlink implements a symbolic link, returning the underlying path when | ||
// Readlink is called. | ||
type symlink struct { | ||
fs.Inode | ||
path string | ||
} | ||
|
||
// Readlink implements fs.NodeReadlinker and returns the symlink's path. | ||
func (s *symlink) Readlink(ctx context.Context) ([]byte, syscall.Errno) { | ||
return []byte(s.path), fs.OK | ||
} | ||
|
||
// readme represents a static read-only text file. | ||
type readme struct { | ||
fs.Inode | ||
} | ||
|
||
const readmeText = ` | ||
When applications attempt to open files in this directory, a remote connection | ||
to the AlloyDB instance of the same name will be established. | ||
For example, when you run one of the following commands, the proxy will initiate | ||
a connection to the corresponding Cloud SQL instance, given you have the correct | ||
IAM permissions. | ||
psql "host=/somedir/project.region.cluster.instance dbname=mydb user=myuser" | ||
The proxy will create a directory with the instance short name, and create a | ||
socket inside that directory with the special Postgres name: .s.PGSQL.5432. | ||
Listing the contents of this directory will show all instances with active | ||
connections. | ||
` | ||
|
||
// Getattr implements fs.NodeGetattrer and indicates that this file is a regular | ||
// file. | ||
func (*readme) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut) syscall.Errno { | ||
*out = fuse.AttrOut{Attr: fuse.Attr{ | ||
Mode: 0444 | syscall.S_IFREG, | ||
Size: uint64(len(readmeText)), | ||
}} | ||
return fs.OK | ||
} | ||
|
||
// Read implements fs.NodeReader and supports incremental reads. | ||
func (*readme) Read(ctx context.Context, f fs.FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { | ||
end := int(off) + len(dest) | ||
if end > len(readmeText) { | ||
end = len(readmeText) | ||
} | ||
return fuse.ReadResultData([]byte(readmeText[off:end])), fs.OK | ||
} | ||
|
||
// Open implements fs.NodeOpener and supports opening the README as a read-only | ||
// file. | ||
func (*readme) Open(ctx context.Context, mode uint32) (fs.FileHandle, uint32, syscall.Errno) { | ||
df := nodefs.NewDataFile([]byte(readmeText)) | ||
rf := nodefs.NewReadOnlyFile(df) | ||
return rf, 0, fs.OK | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package proxy | ||
|
||
import ( | ||
"errors" | ||
"os" | ||
) | ||
|
||
const ( | ||
macfusePath = "/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse" | ||
osxfusePath = "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse" | ||
) | ||
|
||
// SupportsFUSE checks if macfuse or osxfuse are installed on the host by | ||
// looking for both in their known installation location. | ||
func SupportsFUSE() error { | ||
// This code follows the same strategy as hanwen/go-fuse. | ||
// See https://github.com/hanwen/go-fuse/blob/0f728ba15b38579efefc3dc47821882ca18ffea7/fuse/mount_darwin.go#L121-L124. | ||
|
||
// check for macfuse first (newer version of osxfuse) | ||
if _, err := os.Stat(macfusePath); err != nil { | ||
// if that fails, check for osxfuse next | ||
if _, err := os.Stat(osxfusePath); err != nil { | ||
return errors.New("failed to find osxfuse or macfuse: verify FUSE installation and try again (see https://osxfuse.github.io).") | ||
} | ||
} | ||
return nil | ||
} |
Oops, something went wrong.