terracost

package module
v0.4.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2021 License: MIT Imports: 9 Imported by: 0

README

TerraCost logo

TerraCost

PkgGoDev

Go library for estimating Terraform costs using ingested cloud vendor prices. It is meant to be imported and used by programs (API's or standalone) with access to a MySQL-compatible database and the Internet.

Installation

go get github.com/cycloidio/terracost

Requirements

  • Go 1.15 or newer (older may work but are not supported)
  • MySQL database

Provider support

Currently, Terracost supports only a few resources of the AWS provider, however we're actively working on adding more support. See the full list of supported resources on this wiki page.

Usage

Migrating the database
db, err := sql.Open("mysql", "...")

// Can be called on every start of your program, it does nothing if the migrations
// have been executed already.
err := mysql.Migrate(ctx, db, "pricing_migrations")
Ingesting pricing data
db, err := sql.Open("mysql", "...")
backend := mysql.NewBackend(db)

// service can be "AmazonEC2" or "AmazonRDS"
// region is any AWS region, e.g. "us-east-1" or "eu-west-3"
ingester, err := aws.NewIngester(service, region)
err = terracost.IngestPricing(ctx, backend, ingester)
Tracking ingestion progress

We're using the github.com/machinebox/progress library for tracking ingestion progress.

  1. Create a channel that will receive progress updates and set up a goroutine (it will print the bytes ingested out of bytes total and remaining time each time progress update is sent on the channel):
progressCh := make(chan progress.Progress, 0)

go func() {
	for p := range progressCh {
		// Check the docs for all available methods: https://pkg.go.dev/github.com/machinebox/progress#Progress
		fmt.Printf("%d / %d (%s remaining)\n", p.N(), p.Size(), p.Remaining().String())
	}
}()
  1. Initialize an ingester capable of tracking progress (in this example the channel will receive an update every 5 seconds):
ingester, err := aws.NewIngester(service, region, aws.WithProgress(progressCh, 5*time.Second))
  1. Use the ingester as in the previous section.
Estimating a Terraform plan

Plan estimation is possible after all the relevant pricing data have been ingested and stored in the database.

  1. Generate a plan using terraform and convert it to JSON:
terraform plan -out update.tfplan
terraform show -json update.tfplan > tfplan.json
  1. Read the plan file, estimate it and show the resource differences:
db, err := db.Open("mysql", "...")
backend := mysql.NewBackend(db)

file, err := os.Open("path/to/tfplan.json")
plan, err := terracost.EstimateTerraformPlan(ctx, backend, file)

for _, res := range plan.ResourceDifferences() {
    fmt.Printf("%s: %s -> %s\n", res.Address, res.PriorCost().String(), res.PlannedCost().String())
}

Check the documentation for all available fields.

Contributing

For Contributing Guide, please read CONTIBUTING.md.

License

This project is licensed under the MIT license. Please see LICENSE for more details.

Documentation

Overview

Package terracost provides functionality to estimate the costs of infrastructure based on Terrafom plan files.

This package depends on the pricing data located in a MySQL database to work correctly. The following snippet will run all required database migrations and ingest pricing data from AmazonEC2 in eu-west-3 region:

db, err := sql.Open("mysql", "...")
backend := mysql.NewBackend(db)

// Run all database migrations
err = mysql.Migrate(ctx, db, "pricing_migrations")

// Ingest pricing data into the database
ingester := aws.NewIngester("AmazonEC2", "eu-west-3")
err = terracost.IngestPricing(ctx, backend, ingester)

With pricing data in the database, a Terraform plan can be read and estimated:

file, err := os.Open("path/to/tfplan.json")
plan, err := terracost.EstimateTerraformPlan(ctx, backend, file)

for _, res := range plan.ResourceDifferences() {
    fmt.Printf("%s: %s -> %s\n", res.Address, res.PriorCost().String(), res.PlannedCost().String())
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EstimateHCL added in v0.3.0

func EstimateHCL(ctx context.Context, backend Backend, fs afero.Fs, path string, providerInitializers ...terraform.ProviderInitializer) (*cost.Plan, error)

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 EstimateTerraformPlan

func EstimateTerraformPlan(ctx context.Context, backend Backend, plan io.Reader, providerInitializers ...terraform.ProviderInitializer) (*cost.Plan, error)

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 IngestPricing

func IngestPricing(ctx context.Context, backend Backend, ingester Ingester) error

IngestPricing uses the Ingester to load the pricing data and stores it into the Backend.

Types

type Backend

type Backend interface {
	Product() product.Repository
	Price() price.Repository
}

Backend represents a storage method used to store pricing data. It must include concrete implementations of all repositories.

type Ingester

type Ingester interface {
	// Ingest downloads pricing data from a cloud provider and sends prices with their associated products
	// on the returned channel.
	Ingest(ctx context.Context, chSize int) <-chan *price.WithProduct

	// Err returns any potential error.
	Err() error
}

Ingester represents a vendor-specific mechanism to load pricing data.

Directories

Path Synopsis
aws
Package aws enables cost estimation of AWS resources and ingestion of pricing data from AWS.
Package aws enables cost estimation of AWS resources and ingestion of pricing data from AWS.
Package cost defines structures that represent cloud resources and states in a cloud-agnostic, as well as tool-agnostic way.
Package cost defines structures that represent cloud resources and states in a cloud-agnostic, as well as tool-agnostic way.
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.
Package mysql implements the various domain entity repositories and includes a Backend that groups them.
Package mysql implements the various domain entity repositories and includes a Backend that groups them.
Package query defines agnostic structures used to communicate between the tool layer (e.g.
Package query defines agnostic structures used to communicate between the tool layer (e.g.
Package terraform includes functionality related to reading Terraform plan files.
Package terraform includes functionality related to reading Terraform plan files.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL