Cloud cost estimation for Terraform in your CLI
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.
go mod edit -replace github.com/hashicorp/terraform=github.com/cycloidio/[email protected] && go get github.com/cycloidio/terracost
We need to do a -replace
because of https://github.com/golang/go/issues/30354#issuecomment-466557015. We have a custom fork of Terraform and in order
to use TerraCost it needs to be replaced when importing also.
Currently Terracost supports the following providers and with an specific subset of resources from them:
To be able to ingest the pricing data from Google the credentials needed have to have access to Compute Engine API and have also billing enabled. This is needed to be able to fetch the Machine Types, for the SKUs we would only need an normal set of credentials (or even API Key) but as we need both we have to use the more complex one. If you do not know how to activate those permissions, just use the credentials and the import will fail and on the logs will inform of what is missing and how to activate it.
db, err := sql.Open("mysql", "root:password@tcp(IP:3306)/databasename?multiStatements=true")
// Can be called on every start of your program, it does nothing if the migrations
// have been executed already.
err = mysql.Migrate(context.Background(), db, "pricing_migrations")
db, err := sql.Open("mysql", "root:password@tcp(IP:3306)/databasename?multiStatements=true")
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(context.Background(), backend, ingester)
We're using the github.com/machinebox/progress
library for tracking ingestion progress.
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())
}
}()
ingester, err := aws.NewIngester(service, region, aws.WithProgress(progressCh, 5*time.Second))
Plan estimation is possible after all the relevant pricing data have been ingested and stored in the database.
terraform
and convert it to JSON:terraform plan -out update.tfplan
terraform show -json update.tfplan > tfplan.json
db, err := db.Open("mysql", "...")
backend := mysql.NewBackend(db)
file, err := os.Open("path/to/tfplan.json")
plan, err := terracost.EstimateTerraformPlan(context.Background(), backend, file)
for _, res := range plan.ResourceDifferences() {
priorCost, err := res.PriorCost()
plannedCost, err := res.PlannedCost()
fmt.Printf("%s: %s -> %s\n", res.Address, priorCost, plannedCost)
}
Check the documentation for all available fields.
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.
For more examples, please check examples.
For Contributing Guide, please read CONTIBUTING.md.
This project is licensed under the MIT license. Please see LICENSE for more details.
Cycloid is a hybrid cloud DevOps collaboration platform providing end-to-end frameworks to accelerate and industrialize software delivery.
As of now, we have three open-source tools:
...and the functionality of each is also embedded in our DevOps solution, which you can find out more about here.