Repository: cycloidio/terracost (go)

Issue:
Add usage cost
Some resources do not have specific attributes that would be used to calculate the price, this price is set when the resource is used. For this we'll allow a specific file that would specify that usage for the specific resources so we can make a estimation on their usage instead of having a 0 cost.

The format of this file for now will be:

```yaml
resource_type_default_usage:
    aws_lambda_function:
      monthly_requests: 100000 # Monthly requests to the Lambda function.
      request_duration_ms: 500 # Average duration of each request in milliseconds.
```

Pull request description:
usage: Added 'Usage' struct to hold all the supported usage
This is passed when estimating HCL and Plan so they can be conputed with the rest of the configuration

Closes #96 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d90774e..84c45e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
 
 - Support for remote module references
   ([Issue #88](https://github.com/cycloidio/terracost/issues/88))
+- Added 'Usage' support for those options that are not from configuration but from usage of the resource
+  ([Issue #96](https://github.com/cycloidio/terracost/issues/96))
 
 ### Fixed
 
diff --git a/README.md b/README.md
index 29f950d..a4e8713 100644
--- a/README.md
+++ b/README.md
@@ -113,6 +113,10 @@ for _, res := range plan.ResourceDifferences() {
 
 Check the documentation for all available fields.
 
+### Usage estimation
+
+Some resources do cannot be estimated just by the configuration and need some extra usage information, for that we have some default on `usage/usage.go` which are also all the resources and options we support currently and can be overwritten when estimating if passing a custom one instead of the custom Default one.
+
 ## Examples
 
 For more examples, please check [examples](examples/README.md).
diff --git a/estimation.go b/estimation.go
index 79a396a..33a9f49 100644
--- a/estimation.go
+++ b/estimation.go
@@ -9,12 +9,13 @@ import (
 	"github.com/cycloidio/terracost/backend"
 	"github.com/cycloidio/terracost/cost"
 	"github.com/cycloidio/terracost/terraform"
+	"github.com/cycloidio/terracost/usage"
 )
 
 // EstimateTerraformPlan is a helper function that reads a Terraform plan using the provided io.Reader,
 // generates the prior and planned cost.State, and then creates a cost.Plan from them that is returned.
 // It uses the Backend to retrieve the pricing data.
-func EstimateTerraformPlan(ctx context.Context, be backend.Backend, plan io.Reader, providerInitializers ...terraform.ProviderInitializer) (*cost.Plan, error) {
+func EstimateTerraformPlan(ctx context.Context, be backend.Backend, plan io.Reader, u usage.Usage, providerInitializers ...terraform.ProviderInitializer) (*cost.Plan, error) {
 	if len(providerInitializers) == 0 {
 		providerInitializers = getDefaultProviders()
 	}
@@ -23,6 +24,7 @@ func EstimateTerraformPlan(ctx context.Context, be backend.Backend, plan io.Read
 	if err := tfplan.Read(plan); err != nil {
 		return nil, err
 	}
+	tfplan.SetUsage(u)
 
 	priorQueries, err := tfplan.ExtractPriorQueries()
 	if err != nil {
@@ -51,7 +53,7 @@ func EstimateTerraformPlan(ctx context.Context, be backend.Backend, plan io.Read
 // EstimateHCL is a helper function that recursively reads Terraform modules from a directory at the
 // given path and generates a planned cost.State that is returned wrapped in a cost.Plan.
 // It uses the Backend to retrieve the pricing data.
-func EstimateHCL(ctx context.Context, be backend.Backend, fs afero.Fs, path string, providerInitializers ...terraform.ProviderInitializer) (*cost.Plan, error) {
+func EstimateHCL(ctx context.Context, be backend.Backend, fs afero.Fs, path string, u usage.Usage, providerInitializers ...terraform.ProviderInitializer) (*cost.Plan, error) {
 	if len(providerInitializers) == 0 {
 		providerInitializers = getDefaultProviders()
 	}
@@ -60,7 +62,7 @@ func EstimateHCL(ctx context.Context, be backend.Backend, fs afero.Fs, path stri
 		fs = afero.NewOsFs()
 	}
 
-	plannedQueries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, path)
+	plannedQueries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, path, u)
 	if err != nil {
 		return nil, err
 	}
diff --git a/terraform/hcl.go b/terraform/hcl.go
index b737411..ad82115 100644
--- a/terraform/hcl.go
+++ b/terraform/hcl.go
@@ -22,10 +22,11 @@ import (
 	"github.com/zclconf/go-cty/cty"
 
 	"github.com/cycloidio/terracost/query"
+	"github.com/cycloidio/terracost/usage"
 )
 
 // ExtractQueriesFromHCL returns the resources found in the module identified by the modPath.
-func ExtractQueriesFromHCL(fs afero.Fs, providerInitializers []ProviderInitializer, modPath string) ([]query.Resource, error) {
+func ExtractQueriesFromHCL(fs afero.Fs, providerInitializers []ProviderInitializer, modPath string, u usage.Usage) ([]query.Resource, error) {
 	parser := configs.NewParser(fs)
 	mod, diags := parser.LoadConfigDir(modPath)
 	if diags.HasErrors() {
@@ -39,7 +40,7 @@ func ExtractQueriesFromHCL(fs afero.Fs, providerInitializers []ProviderInitializ
 		return nil, err
 	}
 
-	queries, err := extractHCLModule(fs, providers, parser, modPath, "", mod, evalCtx)
+	queries, err := extractHCLModule(fs, providers, parser, modPath, "", mod, evalCtx, u)
 	if err != nil {
 		return nil, err
 	}
@@ -53,7 +54,7 @@ func ExtractQueriesFromHCL(fs afero.Fs, providerInitializers []ProviderInitializ
 }
 
 // extractHCLModule returns the resources found in the provided module.
-func extractHCLModule(fs afero.Fs, providers map[string]Provider, parser *configs.Parser, modPath, modName string, mod *configs.Module, evalCtx *hcl.EvalContext) ([]query.Resource, error) {
+func extractHCLModule(fs afero.Fs, providers map[string]Provider, parser *configs.Parser, modPath, modName string, mod *configs.Module, evalCtx *hcl.EvalContext, u usage.Usage) ([]query.Resource, error) {
 	queries := make([]query.Resource, 0, len(mod.ManagedResources))
 
 	rss := make(map[string]Resource)
@@ -107,6 +108,7 @@ func extractHCLModule(fs afero.Fs, providers map[string]Provider, parser *config
 	}
 
 	for _, r := range rss {
+		r.Values[usage.Key] = u.GetUsage(r.Type)
 		provider := providers[r.ProviderName]
 		queries = append(queries, query.Resource{
 			Address:    r.Address,
@@ -188,7 +190,7 @@ func extractHCLModule(fs afero.Fs, providers map[string]Provider, parser *config
 			nextModPath = fmt.Sprintf("module.%s", mk)
 		}
 
-		qs, err := extractHCLModule(fs, childProvs, parser, p, nextModPath, child, nextEvalCtx)
+		qs, err := extractHCLModule(fs, childProvs, parser, p, nextModPath, child, nextEvalCtx, u)
 		if err != nil {
 			return nil, err
 		}
diff --git a/terraform/plan.go b/terraform/plan.go
index fcf92bb..43e5ed7 100644
--- a/terraform/plan.go
+++ b/terraform/plan.go
@@ -7,11 +7,13 @@ import (
 	"strings"
 
 	"github.com/cycloidio/terracost/query"
+	"github.com/cycloidio/terracost/usage"
 )
 
 // Plan is a representation of a Terraform plan file.
 type Plan struct {
 	providerInitializers map[string]ProviderInitializer
+	usage                usage.Usage
 
 	Configuration Configuration       `json:"configuration"`
 	PriorState    *State              `json:"prior_state"`
@@ -19,6 +21,9 @@ type Plan struct {
 	Variables     map[string]Variable `json:"variables"`
 }
 
+// SetUsage will set the usage of the plan
+func (p *Plan) SetUsage(u usage.Usage) { p.usage = u }
+
 // NewPlan returns an empty Plan.
 func NewPlan(providerInitializers ...ProviderInitializer) *Plan {
 	piMap := make(map[string]ProviderInitializer)
@@ -142,6 +147,7 @@ func (p *Plan) extractModuleQueries(module *Module, resourceProviders map[string
 			continue
 		}
 
+		tfres.Values[usage.Key] = p.usage.GetUsage(tfres.Type)
 		comps := provider.ResourceComponents(nil, tfres)
 		q := query.Resource{
 			Address:    tfres.Address,
diff --git a/usage/usage.go b/usage/usage.go
new file mode 100644
index 0000000..38a9175
--- /dev/null
+++ b/usage/usage.go
@@ -0,0 +1,43 @@
+package usage
+
+const (
+	// Key is the key used to set the usage
+	// on the values passed to the resources
+	Key string = "usage"
+)
+
+// Default is the default Usage that will be used if none is configured
+var Default = Usage{
+	ResourceDefaultTypeUsage: map[string]interface{}{
+		"aws_eks_node_group": map[string]interface{}{
+			"instances":                        15,
+			"operating_system":                 "linux",
+			"reserved_instance_type":           "standard",
+			"reserved_instance_term":           "1_year",
+			"reserved_instance_payment_option": "partial_upfront",
+			"monthly_cpu_credit_hrs":           350,
+			"vcpu_count":                       2,
+		},
+		"aws_efs_file_system": map[string]interface{}{
+			"storage_gb":                         230,
+			"infrequent_access_storage_gb":       100,
+			"monthly_infrequent_access_read_gb":  50,
+			"monthly_infrequent_access_write_gb": 100,
+		},
+	},
+}
+
+// Usage is the struct defining all the configure usages
+type Usage struct {
+	ResourceDefaultTypeUsage map[string]interface{} `json:"resource_default_type_usage",yaml:"resource_default_type_usage"`
+}
+
+// GetUsage will return the usage from the resource rt (ex: aws_instance)
+func (u Usage) GetUsage(rt string) map[string]interface{} {
+	us, ok := u.ResourceDefaultTypeUsage[rt]
+	if ok {
+		return us.(map[string]interface{})
+	}
+
+	return nil
+}


Test patch:
diff --git a/e2e/aws_estimation_test.go b/e2e/aws_estimation_test.go
index 9cdad2f..09a6a2b 100644
--- a/e2e/aws_estimation_test.go
+++ b/e2e/aws_estimation_test.go
@@ -15,6 +15,7 @@ import (
 	"github.com/cycloidio/terracost/price"
 	"github.com/cycloidio/terracost/product"
 	"github.com/cycloidio/terracost/terraform"
+	"github.com/cycloidio/terracost/usage"
 	"github.com/shopspring/decimal"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -142,7 +143,7 @@ func TestAWSEstimation(t *testing.T) {
 			require.NoError(t, err)
 			defer f.Close()
 
-			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, terraformAWSTestProviderInitializer)
+			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default, terraformAWSTestProviderInitializer)
 			require.NoError(t, err)
 
 			pcost, err := plan.PriorCost()
@@ -217,7 +218,7 @@ func TestAWSEstimation(t *testing.T) {
 					return awstf.NewProvider(aws.ProviderName, regCode)
 				},
 			}
-			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, tfpi)
+			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default, tfpi)
 			require.NoError(t, err)
 
 			pcost, err := plan.PriorCost()
@@ -237,7 +238,7 @@ func TestAWSEstimation(t *testing.T) {
 			require.NoError(t, err)
 			defer f.Close()
 
-			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f)
+			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default)
 			require.NoError(t, err)
 
 			pcost, err := plan.PriorCost()
@@ -258,7 +259,7 @@ func TestAWSEstimation(t *testing.T) {
 			require.NoError(t, err)
 			defer f.Close()
 
-			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, terraformAWSTestProviderInitializer)
+			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default, terraformAWSTestProviderInitializer)
 			require.NoError(t, err)
 
 			diffs := plan.ResourceDifferences()
@@ -280,7 +281,7 @@ func TestAWSEstimation(t *testing.T) {
 			require.NoError(t, err)
 			defer f.Close()
 
-			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, terraformAWSTestProviderInitializer)
+			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default, terraformAWSTestProviderInitializer)
 			require.Error(t, err, terraform.ErrNoProviders)
 			require.Nil(t, plan)
 		})
@@ -288,7 +289,7 @@ func TestAWSEstimation(t *testing.T) {
 	t.Run("HCL", func(t *testing.T) {
 		t.Run("Success", func(t *testing.T) {
 
-			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-aws")
+			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-aws", usage.Default)
 			require.NoError(t, err)
 
 			assert.Nil(t, plan.Prior)
@@ -299,7 +300,7 @@ func TestAWSEstimation(t *testing.T) {
 		})
 		t.Run("SuccessMagento", func(t *testing.T) {
 
-			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-magento")
+			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-magento", usage.Default)
 			require.NoError(t, err)
 
 			assert.Nil(t, plan.Prior)
@@ -310,7 +311,7 @@ func TestAWSEstimation(t *testing.T) {
 		})
 		t.Run("SuccessASG", func(t *testing.T) {
 
-			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-asg")
+			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-asg", usage.Default)
 			require.NoError(t, err)
 
 			assert.Nil(t, plan.Prior)
@@ -321,7 +322,7 @@ func TestAWSEstimation(t *testing.T) {
 		})
 		t.Run("SuccessRemote", func(t *testing.T) {
 
-			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-remote")
+			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/aws/stack-remote", usage.Default)
 			require.NoError(t, err)
 
 			assert.Nil(t, plan.Prior)
diff --git a/e2e/azurerm_estimation_test.go b/e2e/azurerm_estimation_test.go
index d8dc69b..8c64b0c 100644
--- a/e2e/azurerm_estimation_test.go
+++ b/e2e/azurerm_estimation_test.go
@@ -11,6 +11,7 @@ import (
 	"github.com/cycloidio/terracost/cost"
 	"github.com/cycloidio/terracost/mysql"
 	"github.com/cycloidio/terracost/testutil"
+	"github.com/cycloidio/terracost/usage"
 	"github.com/shopspring/decimal"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -44,7 +45,7 @@ func TestAzureRMEstimation(t *testing.T) {
 		require.NoError(t, err)
 		defer f.Close()
 
-		plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f)
+		plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default)
 		require.NoError(t, err)
 
 		pcost, err := plan.PriorCost()
@@ -56,7 +57,7 @@ func TestAzureRMEstimation(t *testing.T) {
 		assertCostEqual(t, cost.NewMonthly(decimal.NewFromFloat(64.021), "USD"), pcost)
 	})
 	t.Run("FromHCL", func(t *testing.T) {
-		plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/azurerm/stack-compute")
+		plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/azurerm/stack-compute", usage.Default)
 		require.NoError(t, err)
 
 		assert.Nil(t, plan.Prior)
diff --git a/e2e/gcp_estimation_test.go b/e2e/gcp_estimation_test.go
index 66f0ce2..2357025 100644
--- a/e2e/gcp_estimation_test.go
+++ b/e2e/gcp_estimation_test.go
@@ -11,6 +11,7 @@ import (
 	"github.com/cycloidio/terracost/google"
 	"github.com/cycloidio/terracost/mysql"
 	"github.com/cycloidio/terracost/testutil"
+	"github.com/cycloidio/terracost/usage"
 	"github.com/shopspring/decimal"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -47,7 +48,7 @@ func TestGoogleEstimation(t *testing.T) {
 		require.NoError(t, err)
 		defer f.Close()
 
-		plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f)
+		plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default)
 		require.NoError(t, err)
 
 		pcost, err := plan.PriorCost()
@@ -59,7 +60,7 @@ func TestGoogleEstimation(t *testing.T) {
 		assertCostEqual(t, cost.NewMonthly(decimal.NewFromFloat(39.7258116), "USD"), pcost)
 	})
 	t.Run("FromHCL", func(t *testing.T) {
-		plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/google/stack-compute")
+		plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/google/stack-compute", usage.Default)
 		require.NoError(t, err)
 
 		assert.Nil(t, plan.Prior)
diff --git a/e2e/invalid_estimation_test.go b/e2e/invalid_estimation_test.go
index 9ee9f80..b502a6d 100644
--- a/e2e/invalid_estimation_test.go
+++ b/e2e/invalid_estimation_test.go
@@ -9,6 +9,7 @@ import (
 	costestimation "github.com/cycloidio/terracost"
 	"github.com/cycloidio/terracost/mysql"
 	"github.com/cycloidio/terracost/terraform"
+	"github.com/cycloidio/terracost/usage"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -33,7 +34,7 @@ func TestVMWareEstimation(t *testing.T) {
 			require.NoError(t, err)
 			defer f.Close()
 
-			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, terraformAWSTestProviderInitializer)
+			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default, terraformAWSTestProviderInitializer)
 			require.Error(t, err, terraform.ErrNoQueries)
 			assert.Nil(t, plan)
 		})
@@ -42,7 +43,7 @@ func TestVMWareEstimation(t *testing.T) {
 			require.NoError(t, err)
 			defer f.Close()
 
-			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, terraformAWSTestProviderInitializer)
+			plan, err := costestimation.EstimateTerraformPlan(ctx, backend, f, usage.Default, terraformAWSTestProviderInitializer)
 			require.Error(t, err, terraform.ErrNoKnownProvider)
 			assert.Nil(t, plan)
 		})
@@ -50,12 +51,12 @@ func TestVMWareEstimation(t *testing.T) {
 
 	t.Run("HCL", func(t *testing.T) {
 		t.Run("UnsupportedProvider", func(t *testing.T) {
-			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/invalid/stack-vmware")
+			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/invalid/stack-vmware", usage.Default)
 			assert.Nil(t, plan)
 			assert.Error(t, err, terraform.ErrNoKnownProvider)
 		})
 		t.Run("EmptyTerraform", func(t *testing.T) {
-			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/invalid/stack-empty")
+			plan, err := costestimation.EstimateHCL(ctx, backend, nil, "../testdata/invalid/stack-empty", usage.Default)
 			assert.Nil(t, plan)
 			assert.Error(t, err, terraform.ErrNoQueries)
 		})
diff --git a/terraform/hcl_test.go b/terraform/hcl_test.go
index 42540c9..95b190d 100644
--- a/terraform/hcl_test.go
+++ b/terraform/hcl_test.go
@@ -12,6 +12,7 @@ import (
 	"github.com/cycloidio/terracost/mock"
 	"github.com/cycloidio/terracost/query"
 	"github.com/cycloidio/terracost/terraform"
+	"github.com/cycloidio/terracost/usage"
 )
 
 func TestExtractQueriesFromHCL(t *testing.T) {
@@ -38,6 +39,9 @@ func TestExtractQueriesFromHCL(t *testing.T) {
 						"ami":           "some-ami",
 						"instance_type": "t2.micro",
 						"provider":      ".aws",
+						"usage": map[string]interface{}{
+							"usage": "set_instance",
+						},
 					}, res.Values)
 
 				case "module.ec2.aws_instance.front":
@@ -54,6 +58,9 @@ func TestExtractQueriesFromHCL(t *testing.T) {
 								"volume_type":           "gp2",
 							},
 						},
+						"usage": map[string]interface{}{
+							"usage": "set_instance",
+						},
 					}, res.Values)
 
 				case "module.ec2.aws_elb.front":
@@ -69,14 +76,18 @@ func TestExtractQueriesFromHCL(t *testing.T) {
 								"lb_protocol":       "tcp",
 							},
 						},
+						"usage": map[string]interface{}{
+							"usage": "set_elb",
+						},
 					}, res.Values)
 
 				case "module.ec2.module.ebs.aws_ebs_volume.volume":
 					assert.Equal(t, "aws_ebs_volume", res.Type)
 					assert.Equal(t, "volume", res.Name)
 					assert.Equal(t, map[string]interface{}{
-						"size": float64(20),
-						"type": "gp2",
+						"size":  float64(20),
+						"type":  "gp2",
+						"usage": map[string]interface{}(nil),
 					}, res.Values)
 
 				case "module.rds.aws_db_instance.db":
@@ -88,6 +99,7 @@ func TestExtractQueriesFromHCL(t *testing.T) {
 						"instance_class":    "db.t3.small",
 						"multi_az":          true,
 						"storage_type":      "gp2",
+						"usage":             map[string]interface{}(nil),
 					}, res.Values)
 
 				default:
@@ -99,7 +111,16 @@ func TestExtractQueriesFromHCL(t *testing.T) {
 				return nil
 			})
 
-			queries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, "../testdata/aws/stack-aws")
+			queries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, "../testdata/aws/stack-aws", usage.Usage{
+				ResourceDefaultTypeUsage: map[string]interface{}{
+					"aws_instance": map[string]interface{}{
+						"usage": "set_instance",
+					},
+					"aws_elb": map[string]interface{}{
+						"usage": "set_elb",
+					},
+				},
+			})
 			require.NoError(t, err)
 			require.Len(t, queries, 5)
 			for _, q := range queries {
@@ -120,7 +141,7 @@ func TestExtractQueriesFromHCL(t *testing.T) {
 				},
 			}}
 
-			queries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, "../testdata/aws/stack-aws")
+			queries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, "../testdata/aws/stack-aws", usage.Default)
 			require.Error(t, err)
 			require.Len(t, queries, 0)
 		})
@@ -142,7 +163,7 @@ func TestExtractQueriesFromHCL(t *testing.T) {
 				return nil
 			})
 
-			queries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, "../testdata/aws/stack-aws")
+			queries, err := terraform.ExtractQueriesFromHCL(fs, providerInitializers, "../testdata/aws/stack-aws", usage.Default)
 			require.NoError(t, err)
 			require.Len(t, queries, 5)
 
diff --git a/usage/usage_test.go b/usage/usage_test.go
new file mode 100644
index 0000000..dce0dd2
--- /dev/null
+++ b/usage/usage_test.go
@@ -0,0 +1,23 @@
+package usage_test
+
+import (
+	"testing"
+
+	"github.com/cycloidio/terracost/usage"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGetUsage(t *testing.T) {
+	eu := map[string]interface{}{
+		"something": "else",
+	}
+	us := usage.Usage{
+		ResourceDefaultTypeUsage: map[string]interface{}{
+			"aws_instance": eu,
+		},
+	}
+
+	ru := us.GetUsage("aws_instance")
+	assert.Equal(t, eu, ru)
+
+}