Repository: cycloidio/terracost
Pull request #116 (2024-01-03 09:29:13)

google: return an error if the zone has invalid format
Invalid zones will return an error from now on for google ingester


Patch:
diff --git a/google/ingester.go b/google/ingester.go
index ed94c28..b152544 100644
--- a/google/ingester.go
+++ b/google/ingester.go
@@ -70,13 +70,18 @@ func NewIngester(ctx context.Context, credentialJSON []byte, service, project, z
 		return nil, ErrNotSupportedService
 	}
 
+	region, err := zoneToRegion(zone)
+	if err != nil {
+		return nil, fmt.Errorf("unable to get region from zone: %w", err)
+	}
+
 	ing := &Ingester{
 		credentialJSON: credentialJSON,
 		service:        sid,
 
 		project: project,
 		zone:    zone,
-		region:  zoneToRegion(zone),
+		region:  region,
 
 		ingestionFilter: DefaultFilter,
 	}
@@ -318,8 +323,3 @@ func (ing *Ingester) fetchMachineTypes(ctx context.Context) <-chan *compute.Mach
 func (ing *Ingester) Err() error {
 	return ing.err
 }
-
-// zoneToRegion will transform a europe-west1-b to europe-west1
-func zoneToRegion(z string) string {
-	return strings.Join(strings.Split(z, "-")[0:2], "-")
-}
diff --git a/google/terraform_provider.go b/google/terraform_provider.go
index 2cfd349..414577e 100644
--- a/google/terraform_provider.go
+++ b/google/terraform_provider.go
@@ -3,6 +3,7 @@ package google
 import (
 	googletf "github.com/cycloidio/terracost/google/terraform"
 	"github.com/cycloidio/terracost/terraform"
+	"fmt"
 )
 
 // RegistryName is the fully qualified name under which this provider is stored in the registry.
@@ -16,7 +17,10 @@ var TerraformProviderInitializer = terraform.ProviderInitializer{
 		if !ok {
 			return nil, nil
 		}
-		region := zoneToRegion(z.(string))
+		region, err := zoneToRegion(z.(string))
+		if err != nil {
+			return nil, fmt.Errorf("unable to get region from zone: %w", err)
+		}
 		return googletf.NewProvider(ProviderName, region)
 	},
 }
diff --git a/google/zone.go b/google/zone.go
new file mode 100644
index 0000000..87854da
--- /dev/null
+++ b/google/zone.go
@@ -0,0 +1,16 @@
+package google
+
+import (
+	"strings"
+	"fmt"
+)
+
+// zoneToRegion will transform an europe-west1-b to europe-west1
+func zoneToRegion(z string) (string, error) {
+	spl := strings.Split(z, "-")
+	if len(spl) != 3 {
+		return "", fmt.Errorf("invalid zone: %s", z)
+	}
+
+	return strings.Join(spl[0:2], "-"), nil
+}


Test patch:
diff --git a/google/ingester_test.go b/google/ingester_test.go
index 6e20382..74b2d31 100644
--- a/google/ingester_test.go
+++ b/google/ingester_test.go
@@ -73,4 +73,8 @@ func TestIngester(t *testing.T) {
 		_, err := google.NewIngester(ctx, cred, "service", project, zone, google.WithGCPOption(option.WithEndpoint(ts.URL), option.WithoutAuthentication()))
 		assert.EqualError(t, err, google.ErrNotSupportedService.Error())
 	})
+	t.Run("FailUnsupportedZone", func(t *testing.T) {
+		_, err := google.NewIngester(ctx, cred, google.ComputeEngine.String(), project, "zone", google.WithGCPOption(option.WithEndpoint(ts.URL), option.WithoutAuthentication()))
+		assert.EqualError(t, err, "unable to get region from zone: invalid zone: zone")
+	})
 }
diff --git a/google/zone_test.go b/google/zone_test.go
new file mode 100644
index 0000000..cd1500d
--- /dev/null
+++ b/google/zone_test.go
@@ -0,0 +1,45 @@
+package google
+
+import (
+	"github.com/stretchr/testify/assert"
+	"testing"
+	"fmt"
+)
+
+func TestZoneToRegion(t *testing.T) {
+	type args struct {
+		z string
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+		err  error
+	}{
+		{
+			name: "Success",
+			args: args{
+				z: "europe-west1-b",
+			},
+			want: "europe-west1",
+			err:  nil,
+		},
+		{
+			name: "FailInvalidZone",
+			args: args{
+				z: "zone",
+			},
+			want: "",
+			err:  fmt.Errorf("invalid zone: %s", "zone"),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := zoneToRegion(tt.args.z)
+			if tt.err != nil {
+				assert.EqualError(t, err, tt.err.Error(), "zoneToRegion(%v)", tt.args.z)
+			}
+			assert.Equalf(t, tt.want, got, "zoneToRegion(%v)", tt.args.z)
+		})
+	}
+}