Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
65 changes: 65 additions & 0 deletions providers/gcp/internal/billingguard/billingguard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Package billingguard keeps GCP service tests off the real Cloud Billing
// Catalog. Production code logs and swallows a failed billing-service
// construction, so a test that forgot to inject a fake would otherwise pass
// silently on a CI runner and hit the network on a developer machine.
package billingguard

import (
"bytes"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sync"
"testing"
)

const marker = "failed to create billing service"

type watcher struct {
next io.Writer
mu sync.Mutex
hits []string
}

func (w *watcher) Write(p []byte) (int, error) {
if bytes.Contains(p, []byte(marker)) {
w.mu.Lock()
w.hits = append(w.hits, string(bytes.TrimSpace(p)))
w.mu.Unlock()
}
return w.next.Write(p)
}

// Run is for a package's TestMain. It points Application Default Credentials
// at a missing file and the metadata server at a closed port, so the real
// billing client cannot be built, then fails the package if any test tried.
func Run(m *testing.M) int {
for k, v := range map[string]string{
"GOOGLE_APPLICATION_CREDENTIALS": "/nonexistent/billingguard-no-adc.json",
"GCE_METADATA_HOST": "127.0.0.1:1",
"CLOUDSDK_CONFIG": filepath.Join(os.TempDir(), "billingguard-no-gcloud"),
} {
if err := os.Setenv(k, v); err != nil {
fmt.Fprintf(os.Stderr, "billingguard: cannot isolate %s: %v\n", k, err)
return 1
}
}
if err := os.Unsetenv("GOOGLE_API_KEY"); err != nil {
fmt.Fprintf(os.Stderr, "billingguard: cannot unset GOOGLE_API_KEY: %v\n", err)
return 1
}

w := &watcher{next: os.Stderr}
log.SetOutput(w)
code := m.Run()
if code == 0 && len(w.hits) > 0 {
fmt.Fprintf(os.Stderr, "billingguard: %d test(s) reached the real billing service; inject a BillingService fake:\n", len(w.hits))
for _, h := range w.hits {
fmt.Fprintln(os.Stderr, " "+h)
}
return 1
}
return code
}
2 changes: 2 additions & 0 deletions providers/gcp/services/cloudsql/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ func TestCloudSQLClient_GetOfferingDetails_APIError(t *testing.T) {
func TestCloudSQLClient_GetRecommendations_WithMock(t *testing.T) {
ctx := context.Background()
client, _ := NewClient(ctx, "test-project", "us-central1")
client.SetBillingService(&MockBillingService{err: errors.New("catalog not under test")})

mockIterator := &MockRecommenderIterator{
recommendations: []*recommenderpb.Recommendation{
Expand Down Expand Up @@ -704,6 +705,7 @@ func TestCloudSQLClient_SetterMethods(t *testing.T) {
func TestCloudSQLClient_ConvertGCPRecommendation(t *testing.T) {
ctx := context.Background()
client, _ := NewClient(ctx, "test-project", "us-central1")
client.SetBillingService(&MockBillingService{err: errors.New("catalog not under test")})

gcpRec := &recommenderpb.Recommendation{
Name: "test-rec",
Expand Down
10 changes: 10 additions & 0 deletions providers/gcp/services/cloudsql/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cloudsql

import (
"os"
"testing"

"github.com/LeanerCloud/cloud-commitments-go/providers/gcp/internal/billingguard"
)

func TestMain(m *testing.M) { os.Exit(billingguard.Run(m)) }
10 changes: 10 additions & 0 deletions providers/gcp/services/cloudstorage/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cloudstorage

import (
"os"
"testing"

"github.com/LeanerCloud/cloud-commitments-go/providers/gcp/internal/billingguard"
)

func TestMain(m *testing.M) { os.Exit(billingguard.Run(m)) }
1 change: 1 addition & 0 deletions providers/gcp/services/computeengine/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2367,6 +2367,7 @@ func TestConvertGCPRecommendationVCPUOnlyKeepsNilDetails(t *testing.T) {
func TestGetRecommendationsStringMemoryAmountEndToEnd(t *testing.T) {
ctx := context.Background()
client, _ := NewClient(ctx, "test-project", "us-central1")
client.SetBillingService(&MockBillingService{err: errors.New("catalog not under test")})
input := commitmentOnlyCUDRecommendation()
input.StateInfo = &recommenderpb.RecommendationStateInfo{State: recommenderpb.RecommendationStateInfo_ACTIVE}
memoryOpOf(input).PathValue = &recommenderpb.Operation_Value{Value: structpb.NewStringValue("6144")}
Expand Down
10 changes: 10 additions & 0 deletions providers/gcp/services/computeengine/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package computeengine

import (
"os"
"testing"

"github.com/LeanerCloud/cloud-commitments-go/providers/gcp/internal/billingguard"
)

func TestMain(m *testing.M) { os.Exit(billingguard.Run(m)) }
2 changes: 2 additions & 0 deletions providers/gcp/services/memorystore/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@ func TestMemorystoreClient_GetRecommendations_WithMockClient(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
client, _ := NewClient(ctx, "test-project", "us-central1")
client.SetBillingService(&MockBillingService{err: errors.New("catalog not under test")})

mockClient := &MockRecommenderClient{
recommendations: tt.recommendations,
Expand Down Expand Up @@ -633,6 +634,7 @@ func TestMemorystoreClient_GetRecommendations_WithMockClient(t *testing.T) {
func TestMemorystoreClient_ConvertGCPRecommendation(t *testing.T) {
ctx := context.Background()
client, _ := NewClient(ctx, "test-project", "us-central1")
client.SetBillingService(&MockBillingService{err: errors.New("catalog not under test")})

tests := []struct {
name string
Expand Down
10 changes: 10 additions & 0 deletions providers/gcp/services/memorystore/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package memorystore

import (
"os"
"testing"

"github.com/LeanerCloud/cloud-commitments-go/providers/gcp/internal/billingguard"
)

func TestMain(m *testing.M) { os.Exit(billingguard.Run(m)) }
Loading