Skip to content

Commit

Permalink
Merge pull request #317 from k1LoW/support-GOOGLE_APPLICATION_CREDENT…
Browse files Browse the repository at this point in the history
…IALS_JSON

Support GOOGLE_APPLICATION_CREDENTIALS_JSON
  • Loading branch information
k1LoW authored Sep 29, 2021
2 parents 4409bd3 + c923963 commit 840bbc7
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 27 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ dsn: bq://project-id/dataset-id?creds=/path/to/google_application_credentials.js

To set `GOOGLE_APPLICATION_CREDENTIALS` environment variable, you can use

1. `export GOOGLE_APPLICATION_CREDENTIALS` or `env GOOGLE_APPLICATION_CREDENTIALS`
1. `export GOOGLE_APPLICATION_CREDENTIALS` or `export GOOGLE_APPLICATION_CREDENTIALS_JSON`
2. Add query to DSN
- `?google_application_credentials=/path/to/client_secrets.json`
- `?credentials=/path/to/client_secrets.json`
Expand All @@ -452,7 +452,7 @@ dsn: spanner://project-id/instance-id/dbname?creds=/path/to/google_application_c

To set `GOOGLE_APPLICATION_CREDENTIALS` environment variable, you can use

1. `export GOOGLE_APPLICATION_CREDENTIALS` or `env GOOGLE_APPLICATION_CREDENTIALS`
1. `export GOOGLE_APPLICATION_CREDENTIALS` or `export GOOGLE_APPLICATION_CREDENTIALS_JSON`
2. Add query to DSN
- `?google_application_credentials=/path/to/client_secrets.json`
- `?credentials=/path/to/client_secrets.json`
Expand Down
63 changes: 38 additions & 25 deletions datasource/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/k1LoW/tbls/drivers/bq"
"github.com/k1LoW/tbls/drivers/spanner"
"github.com/k1LoW/tbls/schema"
"google.golang.org/api/option"
)

// AnalyzeBigquery analyze `bq://`
Expand Down Expand Up @@ -42,58 +43,70 @@ func NewBigqueryClient(ctx context.Context, urlstr string) (*bigquery.Client, st
if err != nil {
return nil, "", "", err
}
values := u.Query()
err = setEnvGoogleApplicationCredentials(values)
if err != nil {
return nil, "", "", err
}

splitted := strings.Split(u.Path, "/")

projectID := u.Host
datasetID := splitted[1]

client, err := bigquery.NewClient(ctx, projectID)
values := u.Query()
if err := setEnvGoogleApplicationCredentials(values); err != nil {
return nil, "", "", err
}
var client *bigquery.Client
if os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") == "" && os.Getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON") != "" {
client, err = bigquery.NewClient(ctx, projectID, option.WithCredentialsJSON([]byte(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON"))))
} else {
client, err = bigquery.NewClient(ctx, projectID)
}
return client, projectID, datasetID, err
}

// AnalyzeSpanner analyze `spanner://`
func AnalyzeSpanner(urlstr string) (*schema.Schema, error) {
s := &schema.Schema{}
u, err := url.Parse(urlstr)
ctx := context.Background()
client, db, err := NewSpannerClient(ctx, urlstr)
defer client.Close()

s.Name = db
driver, err := spanner.New(ctx, client)
if err != nil {
return s, err
}

values := u.Query()
err = setEnvGoogleApplicationCredentials(values)
err = driver.Analyze(s)
if err != nil {
return s, err
}
return s, nil
}

// NewSpannerClient returns new cloudspanner.Client
func NewSpannerClient(ctx context.Context, urlstr string) (*cloudspanner.Client, string, error) {
u, err := url.Parse(urlstr)
if err != nil {
return nil, "", err
}

splitted := strings.Split(u.Path, "/")
projectID := u.Host
instanceID := splitted[1]
databaseID := splitted[2]

db := fmt.Sprintf("projects/%s/instances/%s/databases/%s", projectID, instanceID, databaseID)
ctx := context.Background()
client, err := cloudspanner.NewClient(ctx, db)
if err != nil {
return s, err
}
defer client.Close()
s.Name = db

driver, err := spanner.New(ctx, client)
if err != nil {
return s, err
values := u.Query()
if err := setEnvGoogleApplicationCredentials(values); err != nil {
return nil, "", err
}
var client *cloudspanner.Client
if os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") == "" && os.Getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON") != "" {
client, err = cloudspanner.NewClient(ctx, db, option.WithCredentialsJSON([]byte(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON"))))
} else {
client, err = cloudspanner.NewClient(ctx, db)
}
err = driver.Analyze(s)
if err != nil {
return s, err
return nil, "", err
}
return s, nil
return client, db, nil
}

func setEnvGoogleApplicationCredentials(values url.Values) error {
Expand Down
38 changes: 38 additions & 0 deletions datasource/gcp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package datasource

import (
"net/url"
"os"
"testing"
)

func TestSetEnvGoogleApplicationCredentials(t *testing.T) {
tests := []struct {
values url.Values
credsEnv string
want string
}{
{url.Values{}, "", ""},
{url.Values{"google_application_credentials": []string{"path/to/creds.json"}}, "", "path/to/creds.json"},
{url.Values{"credentials": []string{"path/to/creds.json"}}, "", "path/to/creds.json"},
{url.Values{"creds": []string{"path/to/creds.json"}}, "", "path/to/creds.json"},
{url.Values{"invalid": []string{"path/to/creds.json"}}, "", ""},
{url.Values{"creds": []string{"path/to/creds.json"}}, "path/to/creds2.json", "path/to/creds.json"},
{url.Values{}, "path/to/creds2.json", "path/to/creds2.json"},
}
for _, tt := range tests {
_ = os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS")
_ = os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS_JSON")

_ = os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", tt.credsEnv)

if err := setEnvGoogleApplicationCredentials(tt.values); err != nil {
t.Fatal(err)
}

got := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
if got != tt.want {
t.Errorf("got %v\nwant %v", got, tt.want)
}
}
}

0 comments on commit 840bbc7

Please # to comment.