From 04bac27ed8fc62b9303ead2f43b1c2b987c289b4 Mon Sep 17 00:00:00 2001 From: Chris Broadfoot Date: Mon, 13 Jul 2020 23:47:39 -0700 Subject: [PATCH] firestore, datastore: implement DetectProjectID for emulator We can use any project ID when the emulator is being used. Try to look detect a real-looking one, and fallback to a dummy ID. Fixes #1751. --- datastore/datastore.go | 28 ++++++++++++++++++++-------- firestore/client.go | 25 +++++++++++++++++++------ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/datastore/datastore.go b/datastore/datastore.go index bdc09b830be..b930371362c 100644 --- a/datastore/datastore.go +++ b/datastore/datastore.go @@ -75,6 +75,12 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio option.WithoutAuthentication(), option.WithGRPCDialOption(grpc.WithInsecure()), } + if projectID == DetectProjectID { + projectID, _ = detectProjectID(ctx, opts...) + if projectID == "" { + projectID = "dummy-emulator-datastore-project" + } + } } else { o = []option.ClientOption{ option.WithEndpoint(prodAddr), @@ -96,16 +102,11 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio o = append(o, opts...) if projectID == DetectProjectID { - creds, err := transport.Creds(ctx, o...) + detected, err := detectProjectID(ctx, opts...) if err != nil { - return nil, fmt.Errorf("fetching creds: %v", err) + return nil, err } - - if creds.ProjectID == "" { - return nil, errors.New("datastore: see the docs on DetectProjectID") - } - - projectID = creds.ProjectID + projectID = detected } if projectID == "" { @@ -122,6 +123,17 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio }, nil } +func detectProjectID(ctx context.Context, opts ...option.ClientOption) (string, error) { + creds, err := transport.Creds(ctx, opts...) + if err != nil { + return "", fmt.Errorf("fetching creds: %v", err) + } + if creds.ProjectID == "" { + return "", errors.New("datastore: see the docs on DetectProjectID") + } + return creds.ProjectID, nil +} + var ( // ErrInvalidEntityType is returned when functions like Get or Next are // passed a dst or src argument of invalid type. diff --git a/firestore/client.go b/firestore/client.go index 1e6ac8c46b1..3acfd1a1bf1 100644 --- a/firestore/client.go +++ b/firestore/client.go @@ -68,18 +68,21 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio return nil, fmt.Errorf("firestore: dialing address from env var FIRESTORE_EMULATOR_HOST: %s", err) } o = []option.ClientOption{option.WithGRPCConn(conn)} + if projectID == DetectProjectID { + projectID, _ = detectProjectID(ctx, opts...) + if projectID == "" { + projectID = "dummy-emulator-firestore-project" + } + } } o = append(o, opts...) if projectID == DetectProjectID { - creds, err := transport.Creds(ctx, o...) + detected, err := detectProjectID(ctx, o...) if err != nil { - return nil, fmt.Errorf("fetching creds: %v", err) - } - if creds.ProjectID == "" { - return nil, errors.New("firestore: see the docs on DetectProjectID") + return nil, err } - projectID = creds.ProjectID + projectID = detected } vc, err := vkit.NewClient(ctx, o...) @@ -93,7 +96,17 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio databaseID: "(default)", // always "(default)", for now } return c, nil +} +func detectProjectID(ctx context.Context, opts ...option.ClientOption) (string, error) { + creds, err := transport.Creds(ctx, opts...) + if err != nil { + return "", fmt.Errorf("fetching creds: %v", err) + } + if creds.ProjectID == "" { + return "", errors.New("firestore: see the docs on DetectProjectID") + } + return creds.ProjectID, nil } // Close closes any resources held by the client.