Skip to content

Commit

Permalink
Support counts
Browse files Browse the repository at this point in the history
  • Loading branch information
obierlaire committed Feb 18, 2023
1 parent 6ccd625 commit 2aabc5b
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 140 deletions.
2 changes: 2 additions & 0 deletions doc/methodology.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ On the same note, if a resource have a terraform `count` attribute, they will ap
```terraform
resource "google_compute_instance" "foo" {
count = 2
...
}
```

will produce :
Expand Down
7 changes: 7 additions & 0 deletions internal/output/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package output

import (
"fmt"
"sort"
"strings"

"github.com/carboniferio/carbonifer/internal/estimate/estimation"
Expand All @@ -17,6 +18,12 @@ func GenerateReportText(report estimation.EstimationReport) string {
table := tablewriter.NewWriter(tableString)
table.SetHeader([]string{"resource type", "name", "count", "emissions per instance"})

// Default sort
estimations := report.Resources
sort.Slice(estimations, func(i, j int) bool {
return estimations[i].Resource.GetIdentification().Name < estimations[j].Resource.GetIdentification().Name
})

for _, resource := range report.Resources {
table.Append([]string{
resource.Resource.GetIdentification().ResourceType,
Expand Down
48 changes: 24 additions & 24 deletions internal/terraform/gcp/ComputeDiskResource.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
)

func getComputeDiskResourceSpecs(
resource tfjson.ConfigResource,
resource tfjson.StateResource,
dataResources *map[string]resources.DataResource) *resources.ComputeResourceSpecs {

disk := getDisk(resource.Address, resource.Expressions, false, dataResources)
disk := getDisk(resource.Address, resource.AttributeValues, false, dataResources)
hddSize := decimal.Zero
ssdSize := decimal.Zero
if disk.isSSD {
Expand All @@ -33,17 +33,18 @@ type disk struct {
replicationFactor int32
}

func getBootDisk(resourceAddress string, bootDiskBlock map[string]*tfjson.Expression, dataResources *map[string]resources.DataResource) disk {
func getBootDisk(resourceAddress string, bootDiskBlock map[string]interface{}, dataResources *map[string]resources.DataResource) disk {
var disk disk
initParams := bootDiskBlock["initialize_params"].NestedBlocks
for _, initParam := range initParams {
initParams := bootDiskBlock["initialize_params"]
for _, iP := range initParams.([]interface{}) {
initParam := iP.(map[string]interface{})
disk = getDisk(resourceAddress, initParam, true, dataResources)

}
return disk
}

func getDisk(resourceAddress string, diskBlock map[string]*tfjson.Expression, isBootDiskParam bool, dataResources *map[string]resources.DataResource) disk {
func getDisk(resourceAddress string, diskBlock map[string]interface{}, isBootDiskParam bool, dataResources *map[string]resources.DataResource) disk {
disk := disk{
sizeGb: viper.GetFloat64("provider.gcp.boot_disk.size"),
isSSD: true,
Expand All @@ -52,48 +53,49 @@ func getDisk(resourceAddress string, diskBlock map[string]*tfjson.Expression, is

// Is Boot disk
isBootDisk := isBootDiskParam
isBootDiskI := GetConstFromExpression(diskBlock["boot"])
isBootDiskI := diskBlock["boot"]
if isBootDiskI != nil {
isBootDisk = isBootDiskI.(bool)
}

// Get disk type
var diskType string
diskTypeExpr := diskBlock["type"]
if diskTypeExpr == nil {
diskTypeExpr = diskBlock["disk_type"]
}
if diskTypeExpr == nil {
if isBootDisk {
diskType = viper.GetString("provider.gcp.boot_disk.type")
} else {
diskType = viper.GetString("provider.gcp.disk.type")
}
} else {
diskType = diskTypeExpr.ConstantValue.(string)
diskType = diskTypeExpr.(string)
}

if diskType == "pd-standard" {
disk.isSSD = false
}

// Get Disk size
declaredSize := GetConstFromExpression(diskBlock["size"])
declaredSize := diskBlock["size"]
if declaredSize == nil {
declaredSize = GetConstFromExpression(diskBlock["disk_size_gb"])
declaredSize = diskBlock["disk_size_gb"]
}
if declaredSize == nil {
if isBootDisk {
disk.sizeGb = viper.GetFloat64("provider.gcp.boot_disk.size")
} else {
disk.sizeGb = viper.GetFloat64("provider.gcp.disk.size")
}
diskImageLinkExpr, okImage := diskBlock["image"]
if okImage {
for _, ref := range diskImageLinkExpr.References {
image, ok := (*dataResources)[ref]
if ok {
disk.sizeGb = (image.(resources.DataImageResource)).DataImageSpecs.DiskSizeGb
} else {
log.Warningf("%v : Disk image does not have a size declared, considering it default to be 10Gb ", resourceAddress)
}
diskImageLink := diskBlock["image"]
if diskImageLink != nil {
image, ok := (*dataResources)[diskImageLink.(string)]
if ok {
disk.sizeGb = (image.(resources.DataImageResource)).DataImageSpecs.DiskSizeGb
} else {
log.Warningf("%v : Disk image does not have a size declared, considering it default to be 10Gb ", resourceAddress)
}
} else {
log.Warningf("%v : Boot disk size not declared. Please set it! (otherwise we assume 10gb) ", resourceAddress)
Expand All @@ -103,12 +105,10 @@ func getDisk(resourceAddress string, diskBlock map[string]*tfjson.Expression, is
disk.sizeGb = declaredSize.(float64)
}

replicaZonesExpr := diskBlock["replica_zones"]
if replicaZonesExpr != nil {
rz := replicaZonesExpr.ConstantValue.([]interface{})
replicaZones := diskBlock["replica_zones"]
if replicaZones != nil {
rz := replicaZones.([]interface{})
disk.replicationFactor = int32(len(rz))
} else {
disk.replicationFactor = 1
}

return disk
Expand Down
36 changes: 18 additions & 18 deletions internal/terraform/gcp/ComputeResource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,46 @@ import (
)

func getComputeResourceSpecs(
resource tfjson.ConfigResource,
resource tfjson.StateResource,
dataResources *map[string]resources.DataResource, groupZone interface{}) *resources.ComputeResourceSpecs {

machine_type := GetConstFromConfig(&resource, "machine_type").(string)
machine_type := resource.AttributeValues["machine_type"].(string)
var zone string
if groupZone != nil {
zone = groupZone.(string)
} else {
zone = GetConstFromConfig(&resource, "zone").(string)
zone = resource.AttributeValues["zone"].(string)
}

machineType := gcp.GetGCPMachineType(machine_type, zone)
CPUType, ok := GetConstFromConfig(&resource, "cpu_platform").(string)
CPUType, ok := resource.AttributeValues["cpu_platform"].(string)
if !ok {
CPUType = ""
}

var disks []disk
bdExpr, ok_bd := resource.Expressions["boot_disk"]
bd, ok_bd := resource.AttributeValues["boot_disk"]
if ok_bd {
bootDisks := bdExpr.NestedBlocks
bootDisks := bd.([]interface{})
for _, bootDiskBlock := range bootDisks {
bootDisk := getBootDisk(resource.Address, bootDiskBlock, dataResources)
bootDisk := getBootDisk(resource.Address, bootDiskBlock.(map[string]interface{}), dataResources)
disks = append(disks, bootDisk)
}
}

diskExpr, ok_bd := resource.Expressions["disk"]
if ok_bd {
disksBlocks := diskExpr.NestedBlocks
for _, diskBlock := range disksBlocks {

bootDisk := getDisk(resource.Address, diskBlock, false, dataResources)
disks = append(disks, bootDisk)
// TODO Disks
diskListI, ok_disks := resource.AttributeValues["disk"]
if ok_disks {
diskList := diskListI.([]interface{})
for _, diskBlock := range diskList {
disk := getDisk(resource.Address, diskBlock.(map[string]interface{}), false, dataResources)
disks = append(disks, disk)
}
}

sdExpr, ok_sd := resource.Expressions["scratch_disk"]
sd, ok_sd := resource.AttributeValues["scratch_disk"]
if ok_sd {
scratchDisks := sdExpr.NestedBlocks
scratchDisks := sd.([]interface{})
for range scratchDisks {
// Each scratch disk is 375GB
// source: https://cloud.google.com/compute/docs/disks#localssds
Expand All @@ -66,8 +66,8 @@ func getComputeResourceSpecs(
}

gpus := machineType.GPUTypes
gasI := GetConstFromConfig(&resource, "guest_accelerator")
if gasI != nil {
gasI, ok := resource.AttributeValues["guest_accelerator"]
if ok {
guestAccelerators := gasI.([]interface{})
for _, gaI := range guestAccelerators {
ga := gaI.(map[string]interface{})
Expand Down
23 changes: 17 additions & 6 deletions internal/terraform/gcp/ManagedInstanceGroupResource.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,21 @@ import (
log "github.com/sirupsen/logrus"
)

func getComputeInstanceGroupManagerSpecs(tfResource tfjson.ConfigResource, dataResources *map[string]resources.DataResource, resourceTemplates *map[string]*tfjson.ConfigResource) (*resources.ComputeResourceSpecs, int64) {
func getComputeInstanceGroupManagerSpecs(
tfResource tfjson.StateResource,
dataResources *map[string]resources.DataResource,
resourceTemplates *map[string]*tfjson.StateResource,
resourceConfigs *map[string]*tfjson.ConfigResource) (*resources.ComputeResourceSpecs, int64) {

targetSize := int64(0)
targetSizeExpr := GetConstFromConfig(&tfResource, "target_size")
targetSizeExpr := tfResource.AttributeValues["target_size"]
if targetSizeExpr != nil {
targetSize = decimal.NewFromFloat(targetSizeExpr.(float64)).BigInt().Int64()
}
versionExpr := tfResource.Expressions["version"]
var template *tfjson.ConfigResource

var template *tfjson.StateResource
templateConfig := (*resourceConfigs)[tfResource.Address]
versionExpr := templateConfig.Expressions["version"]
if versionExpr != nil {
for _, version := range versionExpr.NestedBlocks {
instanceTemplate := version["instance_template"]
Expand All @@ -30,9 +37,13 @@ func getComputeInstanceGroupManagerSpecs(tfResource tfjson.ConfigResource, dataR
}
}
}

if template != nil {
zone := GetConstFromConfig(&tfResource, "zone").(string)
templateResource := GetResourceTemplate(*template, dataResources, zone)
zone := tfResource.AttributeValues["zone"]
if zone == nil {
log.Fatalf("No zone declared for %v", tfResource.Address)
}
templateResource := GetResourceTemplate(*template, dataResources, zone.(string))
computeTemplate, ok := templateResource.(resources.ComputeResource)
if ok {
return computeTemplate.Specs, targetSize
Expand Down
23 changes: 14 additions & 9 deletions internal/terraform/gcp/ResourceIdentification.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
tfjson "github.com/hashicorp/terraform-json"
)

func getResourceIdentification(resource tfjson.ConfigResource) *resources.ResourceIdentification {
region := GetConstFromConfig(&resource, "region")
func getResourceIdentification(resource tfjson.StateResource) *resources.ResourceIdentification {
region := resource.AttributeValues["region"]
if region == nil {
zone := GetConstFromConfig(&resource, "zone")
replica_zones := GetConstFromConfig(&resource, "replica_zones")
zone := resource.AttributeValues["zone"]
replica_zones := resource.AttributeValues["replica_zones"]
if zone != nil {
region = strings.Join(strings.Split(zone.(string), "-")[:2], "-")
} else if replica_zones != nil {
Expand All @@ -22,14 +22,19 @@ func getResourceIdentification(resource tfjson.ConfigResource) *resources.Resour
region = ""
}
}
selfLinkExpr := GetConstFromConfig(&resource, "self_link")
var selfLink string
if selfLinkExpr != nil {
selfLink = GetConstFromConfig(&resource, "self_link").(string)

selfLink := ""
if resource.AttributeValues["self_link"] != nil {
selfLink = resource.AttributeValues["self_link"].(string)
}

name := resource.Name
if resource.Index != nil {
name = fmt.Sprintf("%v[%v]", resource.Name, resource.Index)
}

return &resources.ResourceIdentification{
Name: resource.Name,
Name: name,
ResourceType: resource.Type,
Provider: providers.GCP,
Region: fmt.Sprint(region),
Expand Down
14 changes: 7 additions & 7 deletions internal/terraform/gcp/SQLInstanceResource.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,38 @@ import (
)

func getSQLResourceSpecs(
resource tfjson.ConfigResource) *resources.ComputeResourceSpecs {
resource tfjson.StateResource) *resources.ComputeResourceSpecs {

replicationFactor := int32(1)
ssdSize := decimal.Zero
hddSize := decimal.Zero
var tier gcp.SqlTier

settingsExpr, ok := resource.Expressions["settings"]
settingsI, ok := resource.AttributeValues["settings"]
if ok {
settings := settingsExpr.NestedBlocks[0]
settings := settingsI.([]interface{})[0].(map[string]interface{})

availabilityType := settings["availability_type"]
if availabilityType.ConstantValue != nil && availabilityType.ConstantValue == "REGIONAL" {
if availabilityType != nil && availabilityType == "REGIONAL" {
replicationFactor = int32(2)
}

tierName := ""
if settings["tier"] != nil {
tierName = settings["tier"].ConstantValue.(string)
tierName = settings["tier"].(string)
}
tier = gcp.GetGCPSQLTier(tierName)

diskTypeI, ok_dt := settings["disk_type"]
diskType := "PD_SSD"
if ok_dt {
diskType = diskTypeI.ConstantValue.(string)
diskType = diskTypeI.(string)
}

diskSizeI, ok_ds := settings["disk_size"]
diskSize := decimal.NewFromFloat(10)
if ok_ds {
diskSize = decimal.NewFromFloat(diskSizeI.ConstantValue.(float64))
diskSize = decimal.NewFromFloat(diskSizeI.(float64))
}

if diskType == "PD_SSD" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import (
tfjson "github.com/hashicorp/terraform-json"
)

func GetResource(tfResource tfjson.ConfigResource, dataResources *map[string]resources.DataResource, resourceTemplates *map[string]*tfjson.ConfigResource) resources.Resource {
func GetResource(
tfResource tfjson.StateResource,
dataResources *map[string]resources.DataResource,
resourceTemplates *map[string]*tfjson.StateResource,
resourceConfigs *map[string]*tfjson.ConfigResource) resources.Resource {

resourceId := getResourceIdentification(tfResource)
if resourceId.ResourceType == "google_compute_instance" {
specs := getComputeResourceSpecs(tfResource, dataResources, nil)
Expand All @@ -30,7 +35,7 @@ func GetResource(tfResource tfjson.ConfigResource, dataResources *map[string]res
}
}
if resourceId.ResourceType == "google_compute_instance_group_manager" {
specs, count := getComputeInstanceGroupManagerSpecs(tfResource, dataResources, resourceTemplates)
specs, count := getComputeInstanceGroupManagerSpecs(tfResource, dataResources, resourceTemplates, resourceConfigs)
if specs != nil {
resourceId.Count = count
return resources.ComputeResource{
Expand All @@ -44,7 +49,7 @@ func GetResource(tfResource tfjson.ConfigResource, dataResources *map[string]res
}
}

func GetResourceTemplate(tfResource tfjson.ConfigResource, dataResources *map[string]resources.DataResource, zone string) resources.Resource {
func GetResourceTemplate(tfResource tfjson.StateResource, dataResources *map[string]resources.DataResource, zone string) resources.Resource {
resourceId := getResourceIdentification(tfResource)
if resourceId.ResourceType == "google_compute_instance_template" {
specs := getComputeResourceSpecs(tfResource, dataResources, zone)
Expand Down
Loading

0 comments on commit 2aabc5b

Please sign in to comment.