Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c51013a
Add dataflow accessor
Deep1998 Jan 9, 2024
c214468
Add enable streaming engine struct tag
Deep1998 Jan 9, 2024
267ec8a
Moved dataflow utils to accessor and creates types.go
Deep1998 Jan 9, 2024
515c2db
Create dataflowutils package
Deep1998 Jan 9, 2024
2965b67
Renamed testing package for dataflow util
Deep1998 Jan 9, 2024
d7cca27
Added unit tests
Deep1998 Jan 10, 2024
60fe811
Added empty test files for clients
Deep1998 Jan 10, 2024
fab0bc4
Move test to same package
Deep1998 Jan 10, 2024
820fc08
Add tests for dataflow client
Deep1998 Jan 23, 2024
84c1f74
Update fake for client test
Deep1998 Jan 23, 2024
86daf58
Make dataflow accessor interface and struct to make it testable
Deep1998 Jan 23, 2024
1f17260
Remove interface from accessor package
Deep1998 Jan 23, 2024
fb9cd9a
Add dataflow accessor interface
Deep1998 Jan 24, 2024
ae27ee4
Add comments to dataflow client and comments on unit tests
Deep1998 Jan 24, 2024
f71b602
Add accessors for storage and spanner.
Deep1998 Jan 9, 2024
f6530b1
Add Unmarshall method
Deep1998 Jan 9, 2024
0c4d854
Rename storageacc and spanner acc to storageaccessor and spanneraccessor
Deep1998 Jan 9, 2024
6694071
Add empty test files
Deep1998 Jan 10, 2024
175321c
Increade version retention period
Deep1998 Jan 23, 2024
d3dd902
Add storage accessor interface and impl
Deep1998 Jan 24, 2024
722ac2a
Add storage client unit tests
Deep1998 Jan 24, 2024
12b7737
Add spanner admin client unit tests
Deep1998 Jan 24, 2024
89823d6
Add spanner instance admin client unit tests
Deep1998 Jan 24, 2024
5bf62ab
Add spanner client unit tests
Deep1998 Jan 24, 2024
9c44518
Add interface and implementor for Spanner Accessor
Deep1998 Jan 24, 2024
9267a13
Add unit test for storage utils
Deep1998 Jan 24, 2024
69534f1
Add unit test for dataflow utils:UnmarshalDataflowConfig
Deep1998 Jan 24, 2024
9f2a931
Add dao
Deep1998 Jan 9, 2024
58ff467
Add dao
Deep1998 Jan 9, 2024
ef22824
Added dao
Deep1998 Jan 9, 2024
dfe6ac7
Add activity interface and one activity
Deep1998 Jan 9, 2024
4f36c2a
Move interface to top level folder
Deep1998 Jan 11, 2024
b68e09a
Add activity interface and one activity
Deep1998 Jan 9, 2024
f482cba
Add create reverse replication workflow
Deep1998 Jan 9, 2024
9941174
Switch slices to utils
Deep1998 Jan 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions accessors/clients/dataflow/dataflow_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2024 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 dataflowclient

import (
"context"
"fmt"
"sync"

dataflow "cloud.google.com/go/dataflow/apiv1beta3"
)

var once sync.Once
var dfClient *dataflow.FlexTemplatesClient

// This function is declared as a global variable to make it testable. The unit
// tests edit this function, acting like a double.
var newFlexTemplatesClient = dataflow.NewFlexTemplatesClient

func GetOrCreateClient(ctx context.Context) (*dataflow.FlexTemplatesClient, error) {
var err error
if dfClient == nil {
once.Do(func() {
dfClient, err = newFlexTemplatesClient(ctx)
})
if err != nil {
return nil, fmt.Errorf("failed to create dataflow client: %v", err)
}
return dfClient, nil
}
return dfClient, nil
}
116 changes: 116 additions & 0 deletions accessors/clients/dataflow/dataflow_client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright 2024 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 dataflowclient

import (
"context"
"fmt"
"os"
"sync"
"testing"

dataflow "cloud.google.com/go/dataflow/apiv1beta3"
"github.com/GoogleCloudPlatform/spanner-migration-tool/logger"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"google.golang.org/api/option"
)

func init() {
logger.Log = zap.NewNop()
}

func TestMain(m *testing.M) {
res := m.Run()
os.Exit(res)
}

func resetTest() {
dfClient = nil
once = sync.Once{}
}

func TestGetOrCreateClient_Basic(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newFlexTemplatesClient
defer func() { newFlexTemplatesClient = oldFunc }()
newFlexTemplatesClient = func(ctx context.Context, opts ...option.ClientOption) (*dataflow.FlexTemplatesClient, error) {
return &dataflow.FlexTemplatesClient{}, nil
}
c, err := GetOrCreateClient(ctx)
assert.NotNil(t, c)
assert.Nil(t, err)
}

func TestGetOrCreateClient_OnlyOnceViaSync(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newFlexTemplatesClient
defer func() { newFlexTemplatesClient = oldFunc }()

newFlexTemplatesClient = func(ctx context.Context, opts ...option.ClientOption) (*dataflow.FlexTemplatesClient, error) {
return &dataflow.FlexTemplatesClient{}, nil
}
c, err := GetOrCreateClient(ctx)
assert.NotNil(t, c)
assert.Nil(t, err)
// Explicitly set the client to nil. Running GetOrCreateClient should not create a
// new client since sync would already be executed.
dfClient = nil
newFlexTemplatesClient = func(ctx context.Context, opts ...option.ClientOption) (*dataflow.FlexTemplatesClient, error) {
return nil, fmt.Errorf("test error")
}
c, err = GetOrCreateClient(ctx)
assert.Nil(t, c)
assert.Nil(t, err)
}

func TestGetOrCreateClient_OnlyOnceViaIf(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newFlexTemplatesClient
defer func() { newFlexTemplatesClient = oldFunc }()

newFlexTemplatesClient = func(ctx context.Context, opts ...option.ClientOption) (*dataflow.FlexTemplatesClient, error) {
return &dataflow.FlexTemplatesClient{}, nil
}
oldC, err := GetOrCreateClient(ctx)
assert.NotNil(t, oldC)
assert.Nil(t, err)

// Explicitly reset once. Running GetOrCreateClient should not create a
// new client the if condition should prevent it.
once = sync.Once{}
newFlexTemplatesClient = func(ctx context.Context, opts ...option.ClientOption) (*dataflow.FlexTemplatesClient, error) {
return nil, fmt.Errorf("test error")
}
newC, err := GetOrCreateClient(ctx)
assert.Equal(t, oldC, newC)
assert.Nil(t, err)
}

func TestGetOrCreateClient_Error(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newFlexTemplatesClient
defer func() { newFlexTemplatesClient = oldFunc }()

newFlexTemplatesClient = func(ctx context.Context, opts ...option.ClientOption) (*dataflow.FlexTemplatesClient, error) {
return nil, fmt.Errorf("test error")
}
c, err := GetOrCreateClient(ctx)
assert.Nil(t, c)
assert.NotNil(t, err)
}
43 changes: 43 additions & 0 deletions accessors/clients/spanner/admin/admin_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2024 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 spanneradmin

import (
"context"
"fmt"
"sync"

database "cloud.google.com/go/spanner/admin/database/apiv1"
)

var once sync.Once
var spannerAdminClient *database.DatabaseAdminClient

// This function is declared as a global variable to make it testable. The unit
// tests edit this function, acting like a double.
var newDatabaseAdminClient = database.NewDatabaseAdminClient

func GetOrCreateClient(ctx context.Context) (*database.DatabaseAdminClient, error) {
var err error
if spannerAdminClient == nil {
once.Do(func() {
spannerAdminClient, err = newDatabaseAdminClient(ctx)
})
if err != nil {
return nil, fmt.Errorf("failed to create spanner admin client: %v", err)
}
return spannerAdminClient, nil
}
return spannerAdminClient, nil
}
116 changes: 116 additions & 0 deletions accessors/clients/spanner/admin/admin_client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright 2024 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 spanneradmin

import (
"context"
"fmt"
"os"
"sync"
"testing"

database "cloud.google.com/go/spanner/admin/database/apiv1"
"github.com/GoogleCloudPlatform/spanner-migration-tool/logger"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"google.golang.org/api/option"
)

func init() {
logger.Log = zap.NewNop()
}

func TestMain(m *testing.M) {
res := m.Run()
os.Exit(res)
}

func resetTest() {
spannerAdminClient = nil
once = sync.Once{}
}

func TestGetOrCreateClient_Basic(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newDatabaseAdminClient
defer func() { newDatabaseAdminClient = oldFunc }()
newDatabaseAdminClient = func(ctx context.Context, opts ...option.ClientOption) (*database.DatabaseAdminClient, error) {
return &database.DatabaseAdminClient{}, nil
}
c, err := GetOrCreateClient(ctx)
assert.NotNil(t, c)
assert.Nil(t, err)
}

func TestGetOrCreateClient_OnlyOnceViaSync(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newDatabaseAdminClient
defer func() { newDatabaseAdminClient = oldFunc }()

newDatabaseAdminClient = func(ctx context.Context, opts ...option.ClientOption) (*database.DatabaseAdminClient, error) {
return &database.DatabaseAdminClient{}, nil
}
c, err := GetOrCreateClient(ctx)
assert.NotNil(t, c)
assert.Nil(t, err)
// Explicitly set the client to nil. Running GetOrCreateClient should not create a
// new client since sync would already be executed.
spannerAdminClient = nil
newDatabaseAdminClient = func(ctx context.Context, opts ...option.ClientOption) (*database.DatabaseAdminClient, error) {
return nil, fmt.Errorf("test error")
}
c, err = GetOrCreateClient(ctx)
assert.Nil(t, c)
assert.Nil(t, err)
}

func TestGetOrCreateClient_OnlyOnceViaIf(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newDatabaseAdminClient
defer func() { newDatabaseAdminClient = oldFunc }()

newDatabaseAdminClient = func(ctx context.Context, opts ...option.ClientOption) (*database.DatabaseAdminClient, error) {
return &database.DatabaseAdminClient{}, nil
}
oldC, err := GetOrCreateClient(ctx)
assert.NotNil(t, oldC)
assert.Nil(t, err)

// Explicitly reset once. Running GetOrCreateClient should not create a
// new client the if condition should prevent it.
once = sync.Once{}
newDatabaseAdminClient = func(ctx context.Context, opts ...option.ClientOption) (*database.DatabaseAdminClient, error) {
return nil, fmt.Errorf("test error")
}
newC, err := GetOrCreateClient(ctx)
assert.Equal(t, oldC, newC)
assert.Nil(t, err)
}

func TestGetOrCreateClient_Error(t *testing.T) {
resetTest()
ctx := context.Background()
oldFunc := newDatabaseAdminClient
defer func() { newDatabaseAdminClient = oldFunc }()

newDatabaseAdminClient = func(ctx context.Context, opts ...option.ClientOption) (*database.DatabaseAdminClient, error) {
return nil, fmt.Errorf("test error")
}
c, err := GetOrCreateClient(ctx)
assert.Nil(t, c)
assert.NotNil(t, err)
}
43 changes: 43 additions & 0 deletions accessors/clients/spanner/client/spanner_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2024 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 spannerclient

import (
"context"
"fmt"
"sync"

sp "cloud.google.com/go/spanner"
)

var once sync.Once
var spannerClient *sp.Client

// This function is declared as a global variable to make it testable. The unit
// tests edit this function, acting like a double.
var newClient = sp.NewClient

func GetOrCreateClient(ctx context.Context, dbURI string) (*sp.Client, error) {
var err error
if spannerClient == nil {
once.Do(func() {
spannerClient, err = newClient(ctx, dbURI)
})
if err != nil {
return nil, fmt.Errorf("failed to create spanner database client: %v", err)
}
return spannerClient, nil
}
return spannerClient, nil
}
Loading