diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index a57d5b9..aacfabf 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -36,7 +36,7 @@ jobs:
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
- terraform_version: 1.3.7
+ terraform_version: 1.4.6
terraform_wrapper: false
- run: terraform version -json
diff --git a/README.md b/README.md
index 058739f..a064dcd 100644
--- a/README.md
+++ b/README.md
@@ -267,6 +267,15 @@ The report is customizable (text or JSON, per hour, month...), cf [Configuration
+### Existing terraform plan file
+
+In case you want to read an existing terraform file, you need to pass it as argument. It can either be a raw tfplan or a json plan.
+This is useful when some variables or credentials are required to run `terraform plan`. In that case `carbonifer plan` won't try to run `terraform plan` for you, and won't expect to have any credentials or variable set (via env var...)
+
+```bash
+carbonifer plan /path/to/my/project.tfplan
+```
+
## Methodology
This tool will:
@@ -299,9 +308,12 @@ See the [Scope](doc/scope.md) document for more details.
## Usage
-`carbonifer [path of terraform files]`
+`carbonifer plan [target]`
-The targeted terraform folder is provided as the only argument. By default, it uses the current folder.
+- `target` can be
+ - a terraform project folder
+ - a terraform plan file (json or raw)
+ - default: the current folder
### Prerequisites
diff --git a/cmd/plan.go b/cmd/plan.go
index 438a040..97bb032 100644
--- a/cmd/plan.go
+++ b/cmd/plan.go
@@ -6,8 +6,7 @@ package cmd
import (
"bufio"
"os"
- "path"
- "strings"
+ "path/filepath"
log "github.com/sirupsen/logrus"
@@ -22,9 +21,21 @@ var test_planCmdHasRun = false
// planCmd represents the plan command
var planCmd = &cobra.Command{
- Use: "plan",
- Short: "Estimate CO2 from your infrastructure code",
- Args: cobra.MaximumNArgs(1),
+ Use: "plan",
+ Long: `Estimate CO2 from your infrastructure code.
+
+The 'plan' command optionally takes a single argument:
+
+ directory :
+ - default: current directory
+ - directory: a terraform project directory
+ - file: a terraform plan file (raw or json)
+Example usages:
+ carbonifer plan
+ carbonifer plan /path/to/terraform/project
+ carbonifer plan /path/to/terraform/plan.json
+ carbonifer plan /path/to/terraform/plan.tfplan`,
+ Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
test_planCmdHasRun = true
log.Debug("Running command 'plan'")
@@ -33,20 +44,23 @@ var planCmd = &cobra.Command{
if err != nil {
log.Fatal(err)
}
+
+ input := workdir
if len(args) != 0 {
- terraformProject := args[0]
- if strings.HasPrefix(terraformProject, "/") {
- workdir = terraformProject
- } else {
- workdir = path.Join(workdir, terraformProject)
+ input = args[0]
+ if !filepath.IsAbs(input) {
+ input = filepath.Join(workdir, input)
}
}
- viper.Set("workdir", workdir)
- log.Debugf("Workdir : %v", workdir)
+ // Generate or Read Terraform plan
+ tfPlan, err := terraform.CarboniferPlan(input)
+ if err != nil {
+ log.Fatal(err)
+ }
// Read resources from terraform plan
- resources, err := terraform.GetResources()
+ resources, err := terraform.GetResources(tfPlan)
if err != nil {
log.Fatal(err)
}
diff --git a/doc/scope.md b/doc/scope.md
index 838b304..37da48c 100644
--- a/doc/scope.md
+++ b/doc/scope.md
@@ -6,6 +6,7 @@
Currently, Carbonifer can read only Terraform files. It has been tested with the following versions:
+- 1.4.6
- 1.3.7
- 1.3.6
diff --git a/internal/terraform/resources.go b/internal/terraform/resources.go
new file mode 100644
index 0000000..e762413
--- /dev/null
+++ b/internal/terraform/resources.go
@@ -0,0 +1,107 @@
+package terraform
+
+import (
+ "encoding/json"
+ "os"
+ "strings"
+
+ "github.com/carboniferio/carbonifer/internal/resources"
+ "github.com/carboniferio/carbonifer/internal/terraform/aws"
+ "github.com/carboniferio/carbonifer/internal/terraform/gcp"
+ "github.com/carboniferio/carbonifer/internal/terraform/tfrefs"
+ tfjson "github.com/hashicorp/terraform-json"
+
+ log "github.com/sirupsen/logrus"
+)
+
+func GetResources(tfPlan *tfjson.Plan) (map[string]resources.Resource, error) {
+
+ log.Debugf("Reading resources from Terraform plan: %d resources", len(tfPlan.PlannedValues.RootModule.Resources))
+ resourcesMap := make(map[string]resources.Resource)
+ terraformRefs := tfrefs.References{
+ ResourceConfigs: map[string]*tfjson.ConfigResource{},
+ ResourceReferences: map[string]*tfjson.StateResource{},
+ DataResources: map[string]resources.DataResource{},
+ ProviderConfigs: map[string]string{},
+ }
+ for _, priorRes := range tfPlan.PlannedValues.RootModule.Resources {
+ log.Debugf("Reading prior state resources %v", priorRes.Address)
+ if priorRes.Mode == "data" {
+ if strings.HasPrefix(priorRes.Type, "google") {
+ dataResource := gcp.GetDataResource(*priorRes)
+ terraformRefs.DataResources[dataResource.GetKey()] = dataResource
+ }
+ }
+ }
+
+ // Find template first
+ for _, res := range tfPlan.PlannedValues.RootModule.Resources {
+ log.Debugf("Reading resource %v", res.Address)
+ if strings.HasPrefix(res.Type, "google") && (strings.HasSuffix(res.Type, "_template") ||
+ strings.HasSuffix(res.Type, "_autoscaler")) {
+ if res.Mode == "managed" {
+ terraformRefs.ResourceReferences[res.Address] = res
+ }
+ }
+ }
+
+ // Index configurations in order to find relationships
+ for _, resConfig := range tfPlan.Config.RootModule.Resources {
+ log.Debugf("Reading resource config %v", resConfig.Address)
+ if strings.HasPrefix(resConfig.Type, "google") {
+ if resConfig.Mode == "managed" {
+ terraformRefs.ResourceConfigs[resConfig.Address] = resConfig
+ }
+ }
+ }
+
+ // Get default values
+ for provider, resConfig := range tfPlan.Config.ProviderConfigs {
+ if provider == "aws" {
+ log.Debugf("Reading provider config %v", resConfig.Name)
+ // TODO #58 Improve way we get default regions (env var, profile...)
+ var region interface{}
+ regionExpr := resConfig.Expressions["region"]
+ if regionExpr != nil {
+ region = regionExpr.ConstantValue
+ } else {
+ if os.Getenv("AWS_REGION") != "" {
+ region = os.Getenv("AWS_REGION")
+ }
+ }
+ if region != nil {
+ terraformRefs.ProviderConfigs["region"] = region.(string)
+ }
+ }
+ }
+
+ // Get All resources
+ for _, res := range tfPlan.PlannedValues.RootModule.Resources {
+ log.Debugf("Reading resource %v", res.Address)
+
+ if res.Mode == "managed" {
+ var resource resources.Resource
+ prefix := strings.Split(res.Type, "_")[0]
+ if prefix == "google" {
+ resource = gcp.GetResource(*res, &terraformRefs)
+ } else if prefix == "aws" {
+ resource = aws.GetResource(*res, &terraformRefs)
+ } else {
+ log.Warnf("Skipping resource %s. Provider not supported : %s", res.Type, prefix)
+ }
+ if resource != nil {
+ resourcesMap[resource.GetAddress()] = resource
+ if log.IsLevelEnabled(log.DebugLevel) {
+ computeJsonStr := ""
+ if resource.IsSupported() {
+ computeJson, _ := json.Marshal(resource)
+ computeJsonStr = string(computeJson)
+ }
+ log.Debugf(" Compute resource : %v", string(computeJsonStr))
+ }
+ }
+ }
+
+ }
+ return resourcesMap, nil
+}
diff --git a/internal/terraform/resources_test.go b/internal/terraform/resources_test.go
new file mode 100644
index 0000000..a62c85a
--- /dev/null
+++ b/internal/terraform/resources_test.go
@@ -0,0 +1,303 @@
+package terraform_test
+
+import (
+ "log"
+ "path"
+ "testing"
+
+ "github.com/carboniferio/carbonifer/internal/providers"
+ "github.com/carboniferio/carbonifer/internal/resources"
+ "github.com/carboniferio/carbonifer/internal/terraform"
+ "github.com/carboniferio/carbonifer/internal/testutils"
+ "github.com/shopspring/decimal"
+ "github.com/spf13/viper"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetResources(t *testing.T) {
+
+ // reset
+ terraform.ResetTerraformExec()
+
+ wd := path.Join(testutils.RootDir, "test/terraform/gcp_1")
+ viper.Set("workdir", wd)
+
+ wantResources := map[string]resources.Resource{
+ "google_compute_disk.first": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "first",
+ ResourceType: "google_compute_disk",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ GpuTypes: nil,
+ HddStorage: decimal.NewFromInt(1024),
+ SsdStorage: decimal.Zero,
+ MemoryMb: 0,
+ VCPUs: 0,
+ CPUType: "",
+ ReplicationFactor: 1,
+ },
+ },
+ "google_compute_instance.first": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "first",
+ ResourceType: "google_compute_instance",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ HddStorage: decimal.Zero,
+ SsdStorage: decimal.NewFromFloat(567).Add(decimal.NewFromFloat(375).Add(decimal.NewFromFloat(375))),
+ MemoryMb: 87040,
+ VCPUs: 12,
+ GpuTypes: []string{
+ "testing-custom-data-file", // Default of a2-highgpu-1g"
+ "nvidia-tesla-k80", // Added by user in main.tf
+ "nvidia-tesla-k80", // Added by user in main.tf
+ },
+ ReplicationFactor: 1,
+ },
+ },
+ "google_compute_instance.second": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "second",
+ ResourceType: "google_compute_instance",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ GpuTypes: nil,
+ HddStorage: decimal.NewFromFloat(10),
+ SsdStorage: decimal.Zero,
+ MemoryMb: 4098,
+ VCPUs: 2,
+ CPUType: "",
+ ReplicationFactor: 1,
+ },
+ },
+ "google_compute_network.vpc_network": resources.UnsupportedResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "vpc_network",
+ ResourceType: "google_compute_network",
+ Provider: providers.GCP,
+ Region: "",
+ Count: 1,
+ },
+ },
+ "google_compute_region_disk.regional-first": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "regional-first",
+ ResourceType: "google_compute_region_disk",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ GpuTypes: nil,
+ HddStorage: decimal.NewFromInt(1024),
+ SsdStorage: decimal.Zero,
+ MemoryMb: 0,
+ VCPUs: 0,
+ CPUType: "",
+ ReplicationFactor: 2,
+ },
+ },
+ "google_compute_subnetwork.first": resources.UnsupportedResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "first",
+ ResourceType: "google_compute_subnetwork",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ },
+ "google_sql_database_instance.instance": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "instance",
+ ResourceType: "google_sql_database_instance",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ GpuTypes: nil,
+ HddStorage: decimal.Zero,
+ SsdStorage: decimal.NewFromFloat(10),
+ MemoryMb: 15360,
+ VCPUs: 4,
+ CPUType: "",
+ ReplicationFactor: 2,
+ },
+ },
+ }
+ tfPlan, _ := terraform.TerraformPlan()
+ resources, _ := terraform.GetResources(tfPlan)
+ assert.Equal(t, len(resources), len(wantResources))
+ for i, resource := range resources {
+ wantResource := wantResources[i]
+ assert.Equal(t, wantResource, resource)
+ }
+}
+
+func TestGetResources_DiskImage(t *testing.T) {
+ testutils.SkipWithCreds(t)
+ // reset
+ terraform.ResetTerraformExec()
+
+ t.Setenv("GOOGLE_OAUTH_ACCESS_TOKEN", "")
+
+ wd := path.Join(testutils.RootDir, "test/terraform/gcp_images")
+ viper.Set("workdir", wd)
+
+ wantResources := map[string]resources.Resource{
+ "google_compute_disk.diskImage": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "diskImage",
+ ResourceType: "google_compute_disk",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ GpuTypes: nil,
+ HddStorage: decimal.New(int64(50), 1),
+ SsdStorage: decimal.Zero,
+ MemoryMb: 0,
+ VCPUs: 0,
+ CPUType: "",
+ ReplicationFactor: 1,
+ },
+ },
+ }
+
+ tfPlan, _ := terraform.TerraformPlan()
+ resourceList, err := terraform.GetResources(tfPlan)
+ if assert.NoError(t, err) {
+ assert.Equal(t, len(wantResources), len(resourceList))
+ for i, resource := range resourceList {
+ wantResource := wantResources[i]
+ log.Println(resource.(resources.ComputeResource).Specs.HddStorage)
+ assert.EqualValues(t, wantResource, resource)
+ }
+ }
+
+}
+
+func TestGetResources_GroupInstance(t *testing.T) {
+ // reset
+ terraform.ResetTerraformExec()
+
+ wd := path.Join(testutils.RootDir, "test/terraform/gcp_group")
+ viper.Set("workdir", wd)
+
+ wantResources := map[string]resources.Resource{
+ "google_compute_network.vpc_network": resources.UnsupportedResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "vpc_network",
+ ResourceType: "google_compute_network",
+ Provider: providers.GCP,
+ Region: "",
+ Count: 1,
+ },
+ },
+ "google_compute_subnetwork.first": resources.UnsupportedResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "first",
+ ResourceType: "google_compute_subnetwork",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ },
+ "google_compute_instance_group_manager.my-group-manager": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "my-group-manager",
+ ResourceType: "google_compute_instance_group_manager",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 5,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ GpuTypes: nil,
+ HddStorage: decimal.NewFromFloat(20),
+ SsdStorage: decimal.Zero,
+ MemoryMb: 8192,
+ VCPUs: 2,
+ CPUType: "",
+ ReplicationFactor: 1,
+ },
+ },
+ }
+
+ tfPlan, _ := terraform.TerraformPlan()
+ resources, err := terraform.GetResources(tfPlan)
+ if assert.NoError(t, err) {
+ for i, resource := range resources {
+ wantResource := wantResources[i]
+ assert.EqualValues(t, wantResource, resource)
+ }
+ }
+
+}
+
+func TestGetResources_InstanceFromTemplate(t *testing.T) {
+ // reset
+ terraform.ResetTerraformExec()
+
+ wd := path.Join(testutils.RootDir, "test/terraform/gcp_cit")
+ viper.Set("workdir", wd)
+
+ wantResources := map[string]resources.Resource{
+ "google_compute_network.vpc_network": resources.UnsupportedResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "vpc_network",
+ ResourceType: "google_compute_network",
+ Provider: providers.GCP,
+ Region: "",
+ Count: 1,
+ },
+ },
+ "google_compute_subnetwork.first": resources.UnsupportedResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "first",
+ ResourceType: "google_compute_subnetwork",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ },
+ "google_compute_instance_from_template.ifromtpl": resources.ComputeResource{
+ Identification: &resources.ResourceIdentification{
+ Name: "ifromtpl",
+ ResourceType: "google_compute_instance_from_template",
+ Provider: providers.GCP,
+ Region: "europe-west9",
+ Count: 1,
+ },
+ Specs: &resources.ComputeResourceSpecs{
+ GpuTypes: nil,
+ HddStorage: decimal.NewFromFloat(20),
+ SsdStorage: decimal.Zero,
+ MemoryMb: 8192,
+ VCPUs: 2,
+ CPUType: "",
+ ReplicationFactor: 1,
+ },
+ },
+ }
+
+ tfPlan, _ := terraform.TerraformPlan()
+ resources, err := terraform.GetResources(tfPlan)
+ if assert.NoError(t, err) {
+ for i, resource := range resources {
+ wantResource := wantResources[i]
+ assert.EqualValues(t, wantResource, resource)
+ }
+ }
+
+}
diff --git a/internal/terraform/terraform.go b/internal/terraform/terraform.go
index 2cc2a06..8870bcd 100644
--- a/internal/terraform/terraform.go
+++ b/internal/terraform/terraform.go
@@ -5,12 +5,9 @@ import (
"encoding/json"
"os"
"os/exec"
+ "path/filepath"
"strings"
- "github.com/carboniferio/carbonifer/internal/resources"
- "github.com/carboniferio/carbonifer/internal/terraform/aws"
- "github.com/carboniferio/carbonifer/internal/terraform/gcp"
- "github.com/carboniferio/carbonifer/internal/terraform/tfrefs"
"github.com/hashicorp/go-version"
"github.com/hashicorp/hc-install/product"
"github.com/hashicorp/hc-install/releases"
@@ -52,6 +49,10 @@ func GetTerraformExec() (*tfexec.Terraform, error) {
return terraformExec, nil
}
+func ResetTerraformExec() {
+ terraformExec = nil
+}
+
func installTerraform() string {
var execPath string
terraformInstallDir := viper.GetString("terraform.path")
@@ -89,24 +90,61 @@ func installTerraform() string {
return execPath
}
-func TerraformPlan() (*tfjson.Plan, error) {
+func TerraformInit() (*tfexec.Terraform, *context.Context, error) {
tf, err := GetTerraformExec()
if err != nil {
- return nil, err
+ return nil, nil, err
}
- log.Debug("Running terraform plan in ", tf.WorkingDir())
+ log.Debug("Running terraform init in ", tf.WorkingDir())
ctx := context.Background()
// Terraform init
err = tf.Init(ctx)
+ if err != nil {
+ return nil, &ctx, err
+ }
+
+ return tf, &ctx, err
+}
+
+func CarboniferPlan(input string) (*tfjson.Plan, error) {
+ fileInfo, err := os.Stat(input)
+ if err != nil {
+ return nil, err
+ }
+
+ // If the path points to a file, run show
+ if !fileInfo.IsDir() {
+ parentDir := filepath.Dir(input)
+ fileName := filepath.Base(input)
+ viper.Set("workdir", parentDir)
+ tfPlan, err := TerraformShow(fileName)
+ return tfPlan, err
+ } else {
+ // If the path points to a directory, run plan
+ viper.Set("workdir", input)
+ tfPlan, err := TerraformPlan()
+ if err != nil {
+ if e, ok := err.(*ProviderAuthError); ok {
+ log.Warnf("Skipping Authentication error: %v", e)
+ } else {
+ return nil, err
+ }
+ }
+ return tfPlan, err
+ }
+}
+
+func TerraformPlan() (*tfjson.Plan, error) {
+ tf, ctx, err := TerraformInit()
if err != nil {
return nil, err
}
// Terraform Validate
- _, err = tf.Validate(ctx)
+ _, err = tf.Validate(*ctx)
if err != nil {
return nil, err
}
@@ -135,19 +173,13 @@ func TerraformPlan() (*tfjson.Plan, error) {
log.Debugf("Running terraform exec %v", tf.ExecPath())
// Run Terraform Plan with an output file
- out := tfexec.Out(tfPlanFile.Name())
- _, err = tf.Plan(ctx, out)
+ err = terraformPlanExec(tf, *ctx, tfPlanFile)
if err != nil {
- if strings.Contains(err.Error(), "invalid authentication credentials") ||
- strings.Contains(err.Error(), "No credentials loaded") ||
- strings.Contains(err.Error(), "no valid credential") {
- return nil, &ProviderAuthError{ParentError: err}
- }
return nil, err
}
// Run Terraform Show reading file outputed in step above
- tfplan, err := tf.ShowPlanFile(ctx, tfPlanFile.Name())
+ tfplan, err := tf.ShowPlanFile(*ctx, tfPlanFile.Name())
if err != nil {
log.Infof("error running Terraform Show: %s", err)
return nil, err
@@ -155,102 +187,52 @@ func TerraformPlan() (*tfjson.Plan, error) {
return tfplan, nil
}
-func GetResources() (map[string]resources.Resource, error) {
- log.Debug("Reading planned resources from Terraform plan")
- tfPlan, err := TerraformPlan()
+func terraformPlanExec(tf *tfexec.Terraform, ctx context.Context, tfPlanFile *os.File) error {
+ out := tfexec.Out(tfPlanFile.Name())
+ _, err := tf.Plan(ctx, out)
+ var authError ProviderAuthError
if err != nil {
- if e, ok := err.(*ProviderAuthError); ok {
- return nil, e
+ uwErr := err.Error()
+ if strings.Contains(uwErr, "invalid authentication credentials") ||
+ strings.Contains(uwErr, "No credentials loaded") ||
+ strings.Contains(uwErr, "no valid credential") {
+ authError = ProviderAuthError{ParentError: err}
+ return &authError
} else {
- log.Fatal(err)
- }
- }
- log.Debugf("Reading resources from Terraform plan: %d resources", len(tfPlan.PlannedValues.RootModule.Resources))
- resourcesMap := make(map[string]resources.Resource)
- terraformRefs := tfrefs.References{
- ResourceConfigs: map[string]*tfjson.ConfigResource{},
- ResourceReferences: map[string]*tfjson.StateResource{},
- DataResources: map[string]resources.DataResource{},
- ProviderConfigs: map[string]string{},
- }
- for _, priorRes := range tfPlan.PlannedValues.RootModule.Resources {
- log.Debugf("Reading prior state resources %v", priorRes.Address)
- if priorRes.Mode == "data" {
- if strings.HasPrefix(priorRes.Type, "google") {
- dataResource := gcp.GetDataResource(*priorRes)
- terraformRefs.DataResources[dataResource.GetKey()] = dataResource
- }
+ log.Errorf("error running Terraform Plan: %s", err)
+ return err
}
}
+ return nil
+}
- // Find template first
- for _, res := range tfPlan.PlannedValues.RootModule.Resources {
- log.Debugf("Reading resource %v", res.Address)
- if strings.HasPrefix(res.Type, "google") && (strings.HasSuffix(res.Type, "_template") ||
- strings.HasSuffix(res.Type, "_autoscaler")) {
- if res.Mode == "managed" {
- terraformRefs.ResourceReferences[res.Address] = res
- }
+func TerraformShow(fileName string) (*tfjson.Plan, error) {
+ if strings.HasSuffix(fileName, ".json") {
+ planFilePath := filepath.Join(viper.GetString("workdir"), fileName)
+ log.Debugf("Reading Terraform plan from %v", planFilePath)
+ jsonFile, err := os.Open(planFilePath)
+ if err != nil {
+ return nil, err
}
- }
-
- // Index configurations in order to find relationships
- for _, resConfig := range tfPlan.Config.RootModule.Resources {
- log.Debugf("Reading resource config %v", resConfig.Address)
- if strings.HasPrefix(resConfig.Type, "google") {
- if resConfig.Mode == "managed" {
- terraformRefs.ResourceConfigs[resConfig.Address] = resConfig
- }
+ defer jsonFile.Close()
+ byteValue, _ := os.ReadFile(planFilePath)
+ var tfplan tfjson.Plan
+ err = json.Unmarshal(byteValue, &tfplan)
+ if err != nil {
+ return nil, err
}
+ return &tfplan, nil
}
- // Get default values
- for provider, resConfig := range tfPlan.Config.ProviderConfigs {
- if provider == "aws" {
- log.Debugf("Reading provider config %v", resConfig.Name)
- // TODO #58 Improve way we get default regions (env var, profile...)
- var region interface{}
- regionExpr := resConfig.Expressions["region"]
- if regionExpr != nil {
- region = regionExpr.ConstantValue
- } else {
- if os.Getenv("AWS_REGION") != "" {
- region = os.Getenv("AWS_REGION")
- }
- }
- if region != nil {
- terraformRefs.ProviderConfigs["region"] = region.(string)
- }
- }
+ tf, ctx, err := TerraformInit()
+ if err != nil {
+ return nil, err
}
- // Get All resources
- for _, res := range tfPlan.PlannedValues.RootModule.Resources {
- log.Debugf("Reading resource %v", res.Address)
-
- if res.Mode == "managed" {
- var resource resources.Resource
- prefix := strings.Split(res.Type, "_")[0]
- if prefix == "google" {
- resource = gcp.GetResource(*res, &terraformRefs)
- } else if prefix == "aws" {
- resource = aws.GetResource(*res, &terraformRefs)
- } else {
- log.Warnf("Skipping resource %s. Provider not supported : %s", res.Type, prefix)
- }
- if resource != nil {
- resourcesMap[resource.GetAddress()] = resource
- if log.IsLevelEnabled(log.DebugLevel) {
- computeJsonStr := ""
- if resource.IsSupported() {
- computeJson, _ := json.Marshal(resource)
- computeJsonStr = string(computeJson)
- }
- log.Debugf(" Compute resource : %v", string(computeJsonStr))
- }
- }
- }
-
+ // Run Terraform Show
+ tfstate, err := tf.ShowPlanFile(*ctx, fileName)
+ if err != nil {
+ return nil, err
}
- return resourcesMap, nil
+ return tfstate, nil
}
diff --git a/internal/terraform/terraform_test.go b/internal/terraform/terraform_test.go
index 9442287..b66cdf8 100644
--- a/internal/terraform/terraform_test.go
+++ b/internal/terraform/terraform_test.go
@@ -5,11 +5,8 @@ import (
"path"
"testing"
- "github.com/carboniferio/carbonifer/internal/providers"
- "github.com/carboniferio/carbonifer/internal/resources"
"github.com/carboniferio/carbonifer/internal/testutils"
_ "github.com/carboniferio/carbonifer/internal/testutils"
- "github.com/shopspring/decimal"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
@@ -18,7 +15,7 @@ import (
func TestGetTerraformExec(t *testing.T) {
// reset
- terraformExec = nil
+ ResetTerraformExec()
viper.Set("workdir", ".")
tfExec, err := GetTerraformExec()
@@ -30,12 +27,12 @@ func TestGetTerraformExec(t *testing.T) {
func TestGetTerraformExec_NotExistingExactVersion(t *testing.T) {
// reset
t.Setenv("PATH", "")
- terraformExec = nil
+ ResetTerraformExec()
wantedVersion := "1.2.0"
viper.Set("workdir", ".")
viper.Set("terraform.version", wantedVersion)
- terraformExec = nil
+ ResetTerraformExec()
tfExec, err := GetTerraformExec()
assert.NoError(t, err)
assert.NotNil(t, tfExec)
@@ -50,7 +47,7 @@ func TestGetTerraformExec_NotExistingExactVersion(t *testing.T) {
func TestGetTerraformExec_NotExistingNoVersion(t *testing.T) {
// reset
t.Setenv("PATH", "")
- terraformExec = nil
+ ResetTerraformExec()
viper.Set("terraform.version", "")
viper.Set("workdir", ".")
@@ -62,7 +59,7 @@ func TestGetTerraformExec_NotExistingNoVersion(t *testing.T) {
func TestTerraformPlan_NoFile(t *testing.T) {
// reset
- terraformExec = nil
+ ResetTerraformExec()
wd := path.Join(testutils.RootDir, "test/terraform/empty")
logrus.Infof("workdir: %v", wd)
@@ -75,7 +72,7 @@ func TestTerraformPlan_NoFile(t *testing.T) {
func TestTerraformPlan_NoTfFile(t *testing.T) {
// reset
- terraformExec = nil
+ ResetTerraformExec()
wd := path.Join(testutils.RootDir, "test/terraform/notTf")
logrus.Infof("workdir: %v", wd)
@@ -88,7 +85,7 @@ func TestTerraformPlan_NoTfFile(t *testing.T) {
func TestTerraformPlan_BadTfFile(t *testing.T) {
// reset
- terraformExec = nil
+ ResetTerraformExec()
wd := path.Join(testutils.RootDir, "test/terraform/badTf")
logrus.Infof("workdir: %v", wd)
@@ -99,303 +96,68 @@ func TestTerraformPlan_BadTfFile(t *testing.T) {
assert.Contains(t, err.Error(), "configuration is invalid")
}
-func TestGetResources(t *testing.T) {
+func TestTerraformPlan_MissingCreds(t *testing.T) {
// reset
- terraformExec = nil
-
- wd := path.Join(testutils.RootDir, "test/terraform/gcp_1")
- viper.Set("workdir", wd)
-
- wantResources := map[string]resources.Resource{
- "google_compute_disk.first": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "first",
- ResourceType: "google_compute_disk",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- Specs: &resources.ComputeResourceSpecs{
- GpuTypes: nil,
- HddStorage: decimal.NewFromInt(1024),
- SsdStorage: decimal.Zero,
- MemoryMb: 0,
- VCPUs: 0,
- CPUType: "",
- ReplicationFactor: 1,
- },
- },
- "google_compute_instance.first": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "first",
- ResourceType: "google_compute_instance",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- Specs: &resources.ComputeResourceSpecs{
- HddStorage: decimal.Zero,
- SsdStorage: decimal.NewFromFloat(567).Add(decimal.NewFromFloat(375).Add(decimal.NewFromFloat(375))),
- MemoryMb: 87040,
- VCPUs: 12,
- GpuTypes: []string{
- "testing-custom-data-file", // Default of a2-highgpu-1g"
- "nvidia-tesla-k80", // Added by user in main.tf
- "nvidia-tesla-k80", // Added by user in main.tf
- },
- ReplicationFactor: 1,
- },
- },
- "google_compute_instance.second": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "second",
- ResourceType: "google_compute_instance",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- Specs: &resources.ComputeResourceSpecs{
- GpuTypes: nil,
- HddStorage: decimal.NewFromFloat(10),
- SsdStorage: decimal.Zero,
- MemoryMb: 4098,
- VCPUs: 2,
- CPUType: "",
- ReplicationFactor: 1,
- },
- },
- "google_compute_network.vpc_network": resources.UnsupportedResource{
- Identification: &resources.ResourceIdentification{
- Name: "vpc_network",
- ResourceType: "google_compute_network",
- Provider: providers.GCP,
- Region: "",
- Count: 1,
- },
- },
- "google_compute_region_disk.regional-first": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "regional-first",
- ResourceType: "google_compute_region_disk",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- Specs: &resources.ComputeResourceSpecs{
- GpuTypes: nil,
- HddStorage: decimal.NewFromInt(1024),
- SsdStorage: decimal.Zero,
- MemoryMb: 0,
- VCPUs: 0,
- CPUType: "",
- ReplicationFactor: 2,
- },
- },
- "google_compute_subnetwork.first": resources.UnsupportedResource{
- Identification: &resources.ResourceIdentification{
- Name: "first",
- ResourceType: "google_compute_subnetwork",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- },
- "google_sql_database_instance.instance": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "instance",
- ResourceType: "google_sql_database_instance",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- Specs: &resources.ComputeResourceSpecs{
- GpuTypes: nil,
- HddStorage: decimal.Zero,
- SsdStorage: decimal.NewFromFloat(10),
- MemoryMb: 15360,
- VCPUs: 4,
- CPUType: "",
- ReplicationFactor: 2,
- },
- },
- }
-
- resources, _ := GetResources()
- assert.Equal(t, len(resources), len(wantResources))
- for i, resource := range resources {
- wantResource := wantResources[i]
- assert.Equal(t, wantResource, resource)
- }
-}
-
-func TestGetResources_MissingCreds(t *testing.T) {
- // reset
- terraformExec = nil
+ ResetTerraformExec()
wd := path.Join(testutils.RootDir, "test/terraform/gcp_images")
viper.Set("workdir", wd)
- _, err := GetResources()
+ _, err := TerraformPlan()
assert.IsType(t, (*ProviderAuthError)(nil), err)
}
-func TestGetResources_DiskImage(t *testing.T) {
- testutils.SkipWithCreds(t)
+func TestTerraformShow_JSON(t *testing.T) {
// reset
- terraformExec = nil
+ ResetTerraformExec()
- t.Setenv("GOOGLE_OAUTH_ACCESS_TOKEN", "")
-
- wd := path.Join(testutils.RootDir, "test/terraform/gcp_images")
- viper.Set("workdir", wd)
+ tfPlan, err := CarboniferPlan("test/terraform/planJson/plan.json")
+ assert.NoError(t, err)
+ assert.Equal(t, tfPlan.TerraformVersion, "1.3.7")
- wantResources := map[string]resources.Resource{
- "google_compute_disk.diskImage": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "diskImage",
- ResourceType: "google_compute_disk",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- Specs: &resources.ComputeResourceSpecs{
- GpuTypes: nil,
- HddStorage: decimal.New(int64(50), 1),
- SsdStorage: decimal.Zero,
- MemoryMb: 0,
- VCPUs: 0,
- CPUType: "",
- ReplicationFactor: 1,
- },
- },
- }
+}
- resourceList, err := GetResources()
- if assert.NoError(t, err) {
- assert.Equal(t, len(wantResources), len(resourceList))
- for i, resource := range resourceList {
- wantResource := wantResources[i]
- log.Println(resource.(resources.ComputeResource).Specs.HddStorage)
- assert.EqualValues(t, wantResource, resource)
- }
- }
+func TestTerraformShow_NotExistJSON(t *testing.T) {
+ // reset
+ ResetTerraformExec()
+ _, err := CarboniferPlan("test/terraform/planJson/plan2.json")
+ assert.Error(t, err)
}
-func TestGetResources_GroupInstance(t *testing.T) {
- testutils.SkipWithCreds(t)
+func TestTerraformShow_RawPlan(t *testing.T) {
// reset
- terraformExec = nil
+ ResetTerraformExec()
- t.Setenv("GOOGLE_OAUTH_ACCESS_TOKEN", "")
+ tfPlan, err := CarboniferPlan("test/terraform/planRaw/plan.tfplan")
+ assert.NoError(t, err)
+ assert.Equal(t, tfPlan.TerraformVersion, "1.4.6")
- wd := path.Join(testutils.RootDir, "test/terraform/gcp_group")
- viper.Set("workdir", wd)
+}
- wantResources := map[string]resources.Resource{
- "google_compute_network.vpc_network": resources.UnsupportedResource{
- Identification: &resources.ResourceIdentification{
- Name: "vpc_network",
- ResourceType: "google_compute_network",
- Provider: providers.GCP,
- Region: "",
- Count: 1,
- },
- },
- "google_compute_subnetwork.first": resources.UnsupportedResource{
- Identification: &resources.ResourceIdentification{
- Name: "first",
- ResourceType: "google_compute_subnetwork",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- },
- "google_compute_instance_group_manager.my-group-manager": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "my-group-manager",
- ResourceType: "google_compute_instance_group_manager",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 5,
- },
- Specs: &resources.ComputeResourceSpecs{
- GpuTypes: nil,
- HddStorage: decimal.NewFromFloat(20),
- SsdStorage: decimal.Zero,
- MemoryMb: 8192,
- VCPUs: 2,
- CPUType: "",
- ReplicationFactor: 1,
- },
- },
- }
+func TestTerraformShow_WithUnsetVar(t *testing.T) {
+ // reset
+ ResetTerraformExec()
- resources, err := GetResources()
- if assert.NoError(t, err) {
- for i, resource := range resources {
- wantResource := wantResources[i]
- assert.EqualValues(t, wantResource, resource)
- }
- }
+ _, err := CarboniferPlan("test/terraform/planRaw")
+ assert.Error(t, err)
+ assert.ErrorContains(t, err, "was required but not supplied")
}
-func TestGetResources_InstanceFromTemplate(t *testing.T) {
- testutils.SkipWithCreds(t)
+func TestTerraformShow_SetVarDifferentFromPlanFile(t *testing.T) {
// reset
- terraformExec = nil
-
- t.Setenv("GOOGLE_OAUTH_ACCESS_TOKEN", "")
-
- wd := path.Join(testutils.RootDir, "test/terraform/gcp_cit")
- viper.Set("workdir", wd)
+ ResetTerraformExec()
- wantResources := map[string]resources.Resource{
- "google_compute_network.vpc_network": resources.UnsupportedResource{
- Identification: &resources.ResourceIdentification{
- Name: "vpc_network",
- ResourceType: "google_compute_network",
- Provider: providers.GCP,
- Region: "",
- Count: 1,
- },
- },
- "google_compute_subnetwork.first": resources.UnsupportedResource{
- Identification: &resources.ResourceIdentification{
- Name: "first",
- ResourceType: "google_compute_subnetwork",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- },
- "google_compute_instance_from_template.ifromtpl": resources.ComputeResource{
- Identification: &resources.ResourceIdentification{
- Name: "ifromtpl",
- ResourceType: "google_compute_instance_from_template",
- Provider: providers.GCP,
- Region: "europe-west9",
- Count: 1,
- },
- Specs: &resources.ComputeResourceSpecs{
- GpuTypes: nil,
- HddStorage: decimal.NewFromFloat(20),
- SsdStorage: decimal.Zero,
- MemoryMb: 8192,
- VCPUs: 2,
- CPUType: "",
- ReplicationFactor: 1,
- },
- },
- }
+ t.Setenv("TF_VAR_machine_type", "f1-medium")
- resources, err := GetResources()
- if assert.NoError(t, err) {
- for i, resource := range resources {
- wantResource := wantResources[i]
- assert.EqualValues(t, wantResource, resource)
- }
- }
+ wd := path.Join(testutils.RootDir, "test/terraform/planRaw")
+ plan, err := CarboniferPlan(wd)
+ assert.NoError(t, err)
+ assert.Equal(t, plan.Variables["machine_type"].Value, "f1-medium")
+ wd2 := path.Join(testutils.RootDir, "test/terraform/planRaw/plan.tfplan")
+ plan2, err2 := CarboniferPlan(wd2)
+ assert.NoError(t, err2)
+ assert.Equal(t, plan2.Variables["machine_type"].Value, "f1-micro")
}
diff --git a/test/terraform/planJson/plan.json b/test/terraform/planJson/plan.json
new file mode 100644
index 0000000..a2409fb
--- /dev/null
+++ b/test/terraform/planJson/plan.json
@@ -0,0 +1,2608 @@
+{
+ "format_version": "1.1",
+ "terraform_version": "1.3.7",
+ "variables": {
+ "instance_count": {
+ "value": 2
+ }
+ },
+ "planned_values": {
+ "root_module": {
+ "resources": [
+ {
+ "address": "google_compute_autoscaler.foobar",
+ "mode": "managed",
+ "type": "google_compute_autoscaler",
+ "name": "foobar",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "autoscaling_policy": [
+ {
+ "cooldown_period": 60,
+ "cpu_utilization": [
+ {
+ "predictive_method": "NONE",
+ "target": 0.5
+ }
+ ],
+ "load_balancing_utilization": [],
+ "max_replicas": 10,
+ "metric": [],
+ "min_replicas": 1,
+ "mode": "ON",
+ "scale_in_control": [],
+ "scaling_schedules": []
+ }
+ ],
+ "description": null,
+ "name": "my-autoscaler",
+ "timeouts": null
+ },
+ "sensitive_values": {
+ "autoscaling_policy": [
+ {
+ "cpu_utilization": [
+ {}
+ ],
+ "load_balancing_utilization": [],
+ "metric": [],
+ "scale_in_control": [],
+ "scaling_schedules": []
+ }
+ ]
+ }
+ },
+ {
+ "address": "google_compute_disk.first",
+ "mode": "managed",
+ "type": "google_compute_disk",
+ "name": "first",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "description": null,
+ "disk_encryption_key": [],
+ "image": null,
+ "labels": null,
+ "name": "cbf-disk-first",
+ "snapshot": null,
+ "source_disk": null,
+ "source_image_encryption_key": [],
+ "source_snapshot_encryption_key": [],
+ "timeouts": null,
+ "type": "pd-standard",
+ "zone": "europe-west9-a"
+ },
+ "sensitive_values": {
+ "disk_encryption_key": [],
+ "source_image_encryption_key": [],
+ "source_snapshot_encryption_key": [],
+ "users": []
+ }
+ },
+ {
+ "address": "google_compute_instance.default[0]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "default",
+ "index": 0,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 6,
+ "values": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [
+ {
+ "disk_encryption_key_raw": null,
+ "mode": "READ_WRITE"
+ }
+ ],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20230206",
+ "size": 564
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "guest_accelerator": [
+ {
+ "count": 2,
+ "type": "nvidia-tesla-k80"
+ }
+ ],
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n1-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "name": "cbf-test-vm",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "sensitive_values": {
+ "advanced_machine_features": [],
+ "attached_disk": [
+ {}
+ ],
+ "boot_disk": [
+ {
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [
+ {}
+ ],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ },
+ {
+ "address": "google_compute_instance.default[1]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "default",
+ "index": 1,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 6,
+ "values": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [
+ {
+ "disk_encryption_key_raw": null,
+ "mode": "READ_WRITE"
+ }
+ ],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20230206",
+ "size": 564
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "guest_accelerator": [
+ {
+ "count": 2,
+ "type": "nvidia-tesla-k80"
+ }
+ ],
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n1-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "name": "cbf-test-vm",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "sensitive_values": {
+ "advanced_machine_features": [],
+ "attached_disk": [
+ {}
+ ],
+ "boot_disk": [
+ {
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [
+ {}
+ ],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ },
+ {
+ "address": "google_compute_instance.foo[0]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "foo",
+ "index": 0,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 6,
+ "values": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "debian-cloud/debian-11"
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n2-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "min_cpu_platform": "Intel Cascade Lake",
+ "name": "cbf-test-other",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "sensitive_values": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ },
+ {
+ "address": "google_compute_instance.foo[1]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "foo",
+ "index": 1,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 6,
+ "values": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "debian-cloud/debian-11"
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n2-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "min_cpu_platform": "Intel Cascade Lake",
+ "name": "cbf-test-other",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "sensitive_values": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ },
+ {
+ "address": "google_compute_instance_from_template.ifromtpl",
+ "mode": "managed",
+ "type": "google_compute_instance_from_template",
+ "name": "ifromtpl",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "can_ip_forward": false,
+ "labels": {
+ "my_key": "my_value"
+ },
+ "name": "instance-from-template",
+ "shielded_instance_config": [],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "sensitive_values": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [],
+ "confidential_instance_config": [],
+ "guest_accelerator": [],
+ "labels": {},
+ "metadata": {},
+ "network_interface": [],
+ "reservation_affinity": [],
+ "resource_policies": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": []
+ }
+ },
+ {
+ "address": "google_compute_instance_template.my-instance-template",
+ "mode": "managed",
+ "type": "google_compute_instance_template",
+ "name": "my-instance-template",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 1,
+ "values": {
+ "advanced_machine_features": [],
+ "can_ip_forward": false,
+ "description": null,
+ "disk": [
+ {
+ "auto_delete": true,
+ "boot": true,
+ "disk_encryption_key": [],
+ "disk_name": null,
+ "disk_size_gb": 20,
+ "labels": null,
+ "resource_policies": null,
+ "source": null,
+ "source_image_encryption_key": [],
+ "source_snapshot": null,
+ "source_snapshot_encryption_key": []
+ }
+ ],
+ "guest_accelerator": [],
+ "instance_description": null,
+ "labels": null,
+ "machine_type": "n2-standard-2",
+ "metadata": null,
+ "metadata_startup_script": null,
+ "min_cpu_platform": null,
+ "name": "my-instance-template",
+ "network_interface": [
+ {
+ "access_config": [],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "network_ip": null,
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "reservation_affinity": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": null,
+ "timeouts": null
+ },
+ "sensitive_values": {
+ "advanced_machine_features": [],
+ "confidential_instance_config": [],
+ "disk": [
+ {
+ "disk_encryption_key": [],
+ "source_image_encryption_key": [],
+ "source_snapshot_encryption_key": []
+ }
+ ],
+ "guest_accelerator": [],
+ "network_interface": [
+ {
+ "access_config": [],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "service_account": [],
+ "shielded_instance_config": []
+ }
+ },
+ {
+ "address": "google_compute_network.vpc_network",
+ "mode": "managed",
+ "type": "google_compute_network",
+ "name": "vpc_network",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "auto_create_subnetworks": false,
+ "delete_default_routes_on_create": false,
+ "description": null,
+ "enable_ula_internal_ipv6": null,
+ "mtu": 1460,
+ "name": "cbf-network",
+ "timeouts": null
+ },
+ "sensitive_values": {}
+ },
+ {
+ "address": "google_compute_region_disk.second",
+ "mode": "managed",
+ "type": "google_compute_region_disk",
+ "name": "second",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "description": null,
+ "disk_encryption_key": [],
+ "labels": null,
+ "name": "cbf-disk-second",
+ "replica_zones": [
+ "europe-west9-a",
+ "europe-west6-b"
+ ],
+ "snapshot": null,
+ "source_disk": null,
+ "source_snapshot_encryption_key": [],
+ "timeouts": null,
+ "type": "pd-standard"
+ },
+ "sensitive_values": {
+ "disk_encryption_key": [],
+ "replica_zones": [
+ false,
+ false
+ ],
+ "source_snapshot_encryption_key": [],
+ "users": []
+ }
+ },
+ {
+ "address": "google_compute_region_instance_group_manager.my-group-manager",
+ "mode": "managed",
+ "type": "google_compute_region_instance_group_manager",
+ "name": "my-group-manager",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "auto_healing_policies": [],
+ "base_instance_name": "managed",
+ "description": null,
+ "distribution_policy_zones": [
+ "europe-west9-a",
+ "europe-west9-b"
+ ],
+ "list_managed_instances_results": "PAGELESS",
+ "name": "my-group-manager",
+ "named_port": [],
+ "stateful_disk": [],
+ "target_pools": null,
+ "target_size": 3,
+ "timeouts": null,
+ "version": [
+ {
+ "name": null,
+ "target_size": []
+ }
+ ],
+ "wait_for_instances": false,
+ "wait_for_instances_status": "STABLE"
+ },
+ "sensitive_values": {
+ "auto_healing_policies": [],
+ "distribution_policy_zones": [
+ false,
+ false
+ ],
+ "named_port": [],
+ "stateful_disk": [],
+ "status": [],
+ "update_policy": [],
+ "version": [
+ {
+ "target_size": []
+ }
+ ]
+ }
+ },
+ {
+ "address": "google_compute_subnetwork.default",
+ "mode": "managed",
+ "type": "google_compute_subnetwork",
+ "name": "default",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "description": null,
+ "ip_cidr_range": "10.0.1.0/24",
+ "ipv6_access_type": null,
+ "log_config": [],
+ "name": "cbf-subnet",
+ "region": "europe-west9",
+ "role": null,
+ "timeouts": null
+ },
+ "sensitive_values": {
+ "log_config": [],
+ "secondary_ip_range": []
+ }
+ },
+ {
+ "address": "google_sql_database_instance.instance",
+ "mode": "managed",
+ "type": "google_sql_database_instance",
+ "name": "instance",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "clone": [],
+ "database_version": "POSTGRES_14",
+ "deletion_protection": true,
+ "name": "my-database-instance",
+ "region": "europe-west9",
+ "restore_backup_context": [],
+ "root_password": null,
+ "settings": [
+ {
+ "activation_policy": "ALWAYS",
+ "active_directory_config": [],
+ "availability_type": "REGIONAL",
+ "collation": null,
+ "database_flags": [],
+ "deletion_protection_enabled": null,
+ "deny_maintenance_period": [],
+ "disk_autoresize": true,
+ "disk_autoresize_limit": 0,
+ "disk_type": "PD_SSD",
+ "insights_config": [],
+ "maintenance_window": [],
+ "password_validation_policy": [],
+ "pricing_plan": "PER_USE",
+ "sql_server_audit_config": [],
+ "tier": "db-g1-small",
+ "time_zone": null
+ }
+ ],
+ "timeouts": null
+ },
+ "sensitive_values": {
+ "available_maintenance_versions": [],
+ "clone": [],
+ "ip_address": [],
+ "replica_configuration": [],
+ "restore_backup_context": [],
+ "server_ca_cert": [],
+ "settings": [
+ {
+ "active_directory_config": [],
+ "backup_configuration": [],
+ "database_flags": [],
+ "deny_maintenance_period": [],
+ "insights_config": [],
+ "ip_configuration": [],
+ "location_preference": [],
+ "maintenance_window": [],
+ "password_validation_policy": [],
+ "sql_server_audit_config": [],
+ "user_labels": {}
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "resource_changes": [
+ {
+ "address": "google_compute_autoscaler.foobar",
+ "mode": "managed",
+ "type": "google_compute_autoscaler",
+ "name": "foobar",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "autoscaling_policy": [
+ {
+ "cooldown_period": 60,
+ "cpu_utilization": [
+ {
+ "predictive_method": "NONE",
+ "target": 0.5
+ }
+ ],
+ "load_balancing_utilization": [],
+ "max_replicas": 10,
+ "metric": [],
+ "min_replicas": 1,
+ "mode": "ON",
+ "scale_in_control": [],
+ "scaling_schedules": []
+ }
+ ],
+ "description": null,
+ "name": "my-autoscaler",
+ "timeouts": null
+ },
+ "after_unknown": {
+ "autoscaling_policy": [
+ {
+ "cpu_utilization": [
+ {}
+ ],
+ "load_balancing_utilization": [],
+ "metric": [],
+ "scale_in_control": [],
+ "scaling_schedules": []
+ }
+ ],
+ "creation_timestamp": true,
+ "id": true,
+ "project": true,
+ "self_link": true,
+ "target": true,
+ "zone": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "autoscaling_policy": [
+ {
+ "cpu_utilization": [
+ {}
+ ],
+ "load_balancing_utilization": [],
+ "metric": [],
+ "scale_in_control": [],
+ "scaling_schedules": []
+ }
+ ]
+ }
+ }
+ },
+ {
+ "address": "google_compute_disk.first",
+ "mode": "managed",
+ "type": "google_compute_disk",
+ "name": "first",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "description": null,
+ "disk_encryption_key": [],
+ "image": null,
+ "labels": null,
+ "name": "cbf-disk-first",
+ "snapshot": null,
+ "source_disk": null,
+ "source_image_encryption_key": [],
+ "source_snapshot_encryption_key": [],
+ "timeouts": null,
+ "type": "pd-standard",
+ "zone": "europe-west9-a"
+ },
+ "after_unknown": {
+ "creation_timestamp": true,
+ "disk_encryption_key": [],
+ "id": true,
+ "label_fingerprint": true,
+ "last_attach_timestamp": true,
+ "last_detach_timestamp": true,
+ "physical_block_size_bytes": true,
+ "project": true,
+ "provisioned_iops": true,
+ "self_link": true,
+ "size": true,
+ "source_disk_id": true,
+ "source_image_encryption_key": [],
+ "source_image_id": true,
+ "source_snapshot_encryption_key": [],
+ "source_snapshot_id": true,
+ "users": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "disk_encryption_key": [],
+ "source_image_encryption_key": [],
+ "source_snapshot_encryption_key": [],
+ "users": []
+ }
+ }
+ },
+ {
+ "address": "google_compute_instance.default[0]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "default",
+ "index": 0,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [
+ {
+ "disk_encryption_key_raw": null,
+ "mode": "READ_WRITE"
+ }
+ ],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20230206",
+ "size": 564
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "guest_accelerator": [
+ {
+ "count": 2,
+ "type": "nvidia-tesla-k80"
+ }
+ ],
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n1-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "name": "cbf-test-vm",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "after_unknown": {
+ "advanced_machine_features": [],
+ "attached_disk": [
+ {
+ "device_name": true,
+ "disk_encryption_key_sha256": true,
+ "kms_key_self_link": true,
+ "source": true
+ }
+ ],
+ "boot_disk": [
+ {
+ "device_name": true,
+ "disk_encryption_key_sha256": true,
+ "initialize_params": [
+ {
+ "labels": true,
+ "type": true
+ }
+ ],
+ "kms_key_self_link": true,
+ "source": true
+ }
+ ],
+ "confidential_instance_config": true,
+ "cpu_platform": true,
+ "current_status": true,
+ "guest_accelerator": [
+ {}
+ ],
+ "id": true,
+ "instance_id": true,
+ "label_fingerprint": true,
+ "metadata_fingerprint": true,
+ "min_cpu_platform": true,
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "nat_ip": true,
+ "network_tier": true
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "ipv6_access_type": true,
+ "name": true,
+ "network": true,
+ "network_ip": true,
+ "stack_type": true,
+ "subnetwork": true,
+ "subnetwork_project": true
+ }
+ ],
+ "project": true,
+ "reservation_affinity": true,
+ "scheduling": true,
+ "scratch_disk": [],
+ "self_link": true,
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ],
+ "tags_fingerprint": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "advanced_machine_features": [],
+ "attached_disk": [
+ {
+ "disk_encryption_key_raw": true
+ }
+ ],
+ "boot_disk": [
+ {
+ "disk_encryption_key_raw": true,
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [
+ {}
+ ],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ }
+ },
+ {
+ "address": "google_compute_instance.default[1]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "default",
+ "index": 1,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [
+ {
+ "disk_encryption_key_raw": null,
+ "mode": "READ_WRITE"
+ }
+ ],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20230206",
+ "size": 564
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "guest_accelerator": [
+ {
+ "count": 2,
+ "type": "nvidia-tesla-k80"
+ }
+ ],
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n1-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "name": "cbf-test-vm",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "after_unknown": {
+ "advanced_machine_features": [],
+ "attached_disk": [
+ {
+ "device_name": true,
+ "disk_encryption_key_sha256": true,
+ "kms_key_self_link": true,
+ "source": true
+ }
+ ],
+ "boot_disk": [
+ {
+ "device_name": true,
+ "disk_encryption_key_sha256": true,
+ "initialize_params": [
+ {
+ "labels": true,
+ "type": true
+ }
+ ],
+ "kms_key_self_link": true,
+ "source": true
+ }
+ ],
+ "confidential_instance_config": true,
+ "cpu_platform": true,
+ "current_status": true,
+ "guest_accelerator": [
+ {}
+ ],
+ "id": true,
+ "instance_id": true,
+ "label_fingerprint": true,
+ "metadata_fingerprint": true,
+ "min_cpu_platform": true,
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "nat_ip": true,
+ "network_tier": true
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "ipv6_access_type": true,
+ "name": true,
+ "network": true,
+ "network_ip": true,
+ "stack_type": true,
+ "subnetwork": true,
+ "subnetwork_project": true
+ }
+ ],
+ "project": true,
+ "reservation_affinity": true,
+ "scheduling": true,
+ "scratch_disk": [],
+ "self_link": true,
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ],
+ "tags_fingerprint": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "advanced_machine_features": [],
+ "attached_disk": [
+ {
+ "disk_encryption_key_raw": true
+ }
+ ],
+ "boot_disk": [
+ {
+ "disk_encryption_key_raw": true,
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [
+ {}
+ ],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ }
+ },
+ {
+ "address": "google_compute_instance.foo[0]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "foo",
+ "index": 0,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "debian-cloud/debian-11"
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n2-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "min_cpu_platform": "Intel Cascade Lake",
+ "name": "cbf-test-other",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "after_unknown": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "device_name": true,
+ "disk_encryption_key_sha256": true,
+ "initialize_params": [
+ {
+ "labels": true,
+ "size": true,
+ "type": true
+ }
+ ],
+ "kms_key_self_link": true,
+ "source": true
+ }
+ ],
+ "confidential_instance_config": true,
+ "cpu_platform": true,
+ "current_status": true,
+ "guest_accelerator": true,
+ "id": true,
+ "instance_id": true,
+ "label_fingerprint": true,
+ "metadata_fingerprint": true,
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "nat_ip": true,
+ "network_tier": true
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "ipv6_access_type": true,
+ "name": true,
+ "network": true,
+ "network_ip": true,
+ "stack_type": true,
+ "subnetwork": true,
+ "subnetwork_project": true
+ }
+ ],
+ "project": true,
+ "reservation_affinity": true,
+ "scheduling": true,
+ "scratch_disk": [],
+ "self_link": true,
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ],
+ "tags_fingerprint": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "disk_encryption_key_raw": true,
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ }
+ },
+ {
+ "address": "google_compute_instance.foo[1]",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "foo",
+ "index": 1,
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "advanced_machine_features": [],
+ "allow_stopping_for_update": null,
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "auto_delete": true,
+ "disk_encryption_key_raw": null,
+ "initialize_params": [
+ {
+ "image": "debian-cloud/debian-11"
+ }
+ ],
+ "mode": "READ_WRITE"
+ }
+ ],
+ "can_ip_forward": false,
+ "deletion_protection": false,
+ "description": null,
+ "desired_status": null,
+ "enable_display": null,
+ "hostname": null,
+ "labels": null,
+ "machine_type": "n2-standard-2",
+ "metadata": null,
+ "metadata_startup_script": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask",
+ "min_cpu_platform": "Intel Cascade Lake",
+ "name": "cbf-test-other",
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "public_ptr_domain_name": null
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "resource_policies": null,
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ "ssh"
+ ],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "after_unknown": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "device_name": true,
+ "disk_encryption_key_sha256": true,
+ "initialize_params": [
+ {
+ "labels": true,
+ "size": true,
+ "type": true
+ }
+ ],
+ "kms_key_self_link": true,
+ "source": true
+ }
+ ],
+ "confidential_instance_config": true,
+ "cpu_platform": true,
+ "current_status": true,
+ "guest_accelerator": true,
+ "id": true,
+ "instance_id": true,
+ "label_fingerprint": true,
+ "metadata_fingerprint": true,
+ "network_interface": [
+ {
+ "access_config": [
+ {
+ "nat_ip": true,
+ "network_tier": true
+ }
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "ipv6_access_type": true,
+ "name": true,
+ "network": true,
+ "network_ip": true,
+ "stack_type": true,
+ "subnetwork": true,
+ "subnetwork_project": true
+ }
+ ],
+ "project": true,
+ "reservation_affinity": true,
+ "scheduling": true,
+ "scratch_disk": [],
+ "self_link": true,
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ],
+ "tags_fingerprint": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [
+ {
+ "disk_encryption_key_raw": true,
+ "initialize_params": [
+ {
+ "labels": {}
+ }
+ ]
+ }
+ ],
+ "confidential_instance_config": [],
+ "guest_accelerator": [],
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": [
+ false
+ ]
+ }
+ }
+ },
+ {
+ "address": "google_compute_instance_from_template.ifromtpl",
+ "mode": "managed",
+ "type": "google_compute_instance_from_template",
+ "name": "ifromtpl",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "can_ip_forward": false,
+ "labels": {
+ "my_key": "my_value"
+ },
+ "name": "instance-from-template",
+ "shielded_instance_config": [],
+ "timeouts": null,
+ "zone": "europe-west9-a"
+ },
+ "after_unknown": {
+ "advanced_machine_features": true,
+ "allow_stopping_for_update": true,
+ "attached_disk": true,
+ "boot_disk": true,
+ "confidential_instance_config": true,
+ "cpu_platform": true,
+ "current_status": true,
+ "deletion_protection": true,
+ "description": true,
+ "desired_status": true,
+ "enable_display": true,
+ "guest_accelerator": true,
+ "hostname": true,
+ "id": true,
+ "instance_id": true,
+ "label_fingerprint": true,
+ "labels": {},
+ "machine_type": true,
+ "metadata": true,
+ "metadata_fingerprint": true,
+ "metadata_startup_script": true,
+ "min_cpu_platform": true,
+ "network_interface": true,
+ "project": true,
+ "reservation_affinity": true,
+ "resource_policies": true,
+ "scheduling": true,
+ "scratch_disk": true,
+ "self_link": true,
+ "service_account": true,
+ "shielded_instance_config": [],
+ "source_instance_template": true,
+ "tags": true,
+ "tags_fingerprint": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "advanced_machine_features": [],
+ "attached_disk": [],
+ "boot_disk": [],
+ "confidential_instance_config": [],
+ "guest_accelerator": [],
+ "labels": {},
+ "metadata": {},
+ "network_interface": [],
+ "reservation_affinity": [],
+ "resource_policies": [],
+ "scheduling": [],
+ "scratch_disk": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": []
+ }
+ }
+ },
+ {
+ "address": "google_compute_instance_template.my-instance-template",
+ "mode": "managed",
+ "type": "google_compute_instance_template",
+ "name": "my-instance-template",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "advanced_machine_features": [],
+ "can_ip_forward": false,
+ "description": null,
+ "disk": [
+ {
+ "auto_delete": true,
+ "boot": true,
+ "disk_encryption_key": [],
+ "disk_name": null,
+ "disk_size_gb": 20,
+ "labels": null,
+ "resource_policies": null,
+ "source": null,
+ "source_image_encryption_key": [],
+ "source_snapshot": null,
+ "source_snapshot_encryption_key": []
+ }
+ ],
+ "guest_accelerator": [],
+ "instance_description": null,
+ "labels": null,
+ "machine_type": "n2-standard-2",
+ "metadata": null,
+ "metadata_startup_script": null,
+ "min_cpu_platform": null,
+ "name": "my-instance-template",
+ "network_interface": [
+ {
+ "access_config": [],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "network_ip": null,
+ "nic_type": null,
+ "queue_count": null
+ }
+ ],
+ "reservation_affinity": [],
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags": null,
+ "timeouts": null
+ },
+ "after_unknown": {
+ "advanced_machine_features": [],
+ "confidential_instance_config": true,
+ "disk": [
+ {
+ "device_name": true,
+ "disk_encryption_key": [],
+ "disk_type": true,
+ "interface": true,
+ "mode": true,
+ "source_image": true,
+ "source_image_encryption_key": [],
+ "source_snapshot_encryption_key": [],
+ "type": true
+ }
+ ],
+ "guest_accelerator": [],
+ "id": true,
+ "metadata_fingerprint": true,
+ "name_prefix": true,
+ "network_interface": [
+ {
+ "access_config": [],
+ "alias_ip_range": [],
+ "ipv6_access_config": [],
+ "ipv6_access_type": true,
+ "name": true,
+ "network": true,
+ "stack_type": true,
+ "subnetwork": true,
+ "subnetwork_project": true
+ }
+ ],
+ "project": true,
+ "region": true,
+ "reservation_affinity": [],
+ "scheduling": true,
+ "self_link": true,
+ "service_account": [],
+ "shielded_instance_config": [],
+ "tags_fingerprint": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "advanced_machine_features": [],
+ "confidential_instance_config": [],
+ "disk": [
+ {
+ "disk_encryption_key": [],
+ "source_image_encryption_key": [],
+ "source_snapshot_encryption_key": []
+ }
+ ],
+ "guest_accelerator": [],
+ "network_interface": [
+ {
+ "access_config": [],
+ "alias_ip_range": [],
+ "ipv6_access_config": []
+ }
+ ],
+ "reservation_affinity": [],
+ "scheduling": [],
+ "service_account": [],
+ "shielded_instance_config": []
+ }
+ }
+ },
+ {
+ "address": "google_compute_network.vpc_network",
+ "mode": "managed",
+ "type": "google_compute_network",
+ "name": "vpc_network",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "auto_create_subnetworks": false,
+ "delete_default_routes_on_create": false,
+ "description": null,
+ "enable_ula_internal_ipv6": null,
+ "mtu": 1460,
+ "name": "cbf-network",
+ "timeouts": null
+ },
+ "after_unknown": {
+ "gateway_ipv4": true,
+ "id": true,
+ "internal_ipv6_range": true,
+ "project": true,
+ "routing_mode": true,
+ "self_link": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {}
+ }
+ },
+ {
+ "address": "google_compute_region_disk.second",
+ "mode": "managed",
+ "type": "google_compute_region_disk",
+ "name": "second",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "description": null,
+ "disk_encryption_key": [],
+ "labels": null,
+ "name": "cbf-disk-second",
+ "replica_zones": [
+ "europe-west9-a",
+ "europe-west6-b"
+ ],
+ "snapshot": null,
+ "source_disk": null,
+ "source_snapshot_encryption_key": [],
+ "timeouts": null,
+ "type": "pd-standard"
+ },
+ "after_unknown": {
+ "creation_timestamp": true,
+ "disk_encryption_key": [],
+ "id": true,
+ "label_fingerprint": true,
+ "last_attach_timestamp": true,
+ "last_detach_timestamp": true,
+ "physical_block_size_bytes": true,
+ "project": true,
+ "region": true,
+ "replica_zones": [
+ false,
+ false
+ ],
+ "self_link": true,
+ "size": true,
+ "source_disk_id": true,
+ "source_snapshot_encryption_key": [],
+ "source_snapshot_id": true,
+ "users": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "disk_encryption_key": [],
+ "replica_zones": [
+ false,
+ false
+ ],
+ "source_snapshot_encryption_key": [],
+ "users": []
+ }
+ }
+ },
+ {
+ "address": "google_compute_region_instance_group_manager.my-group-manager",
+ "mode": "managed",
+ "type": "google_compute_region_instance_group_manager",
+ "name": "my-group-manager",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "auto_healing_policies": [],
+ "base_instance_name": "managed",
+ "description": null,
+ "distribution_policy_zones": [
+ "europe-west9-a",
+ "europe-west9-b"
+ ],
+ "list_managed_instances_results": "PAGELESS",
+ "name": "my-group-manager",
+ "named_port": [],
+ "stateful_disk": [],
+ "target_pools": null,
+ "target_size": 3,
+ "timeouts": null,
+ "version": [
+ {
+ "name": null,
+ "target_size": []
+ }
+ ],
+ "wait_for_instances": false,
+ "wait_for_instances_status": "STABLE"
+ },
+ "after_unknown": {
+ "auto_healing_policies": [],
+ "distribution_policy_target_shape": true,
+ "distribution_policy_zones": [
+ false,
+ false
+ ],
+ "fingerprint": true,
+ "id": true,
+ "instance_group": true,
+ "named_port": [],
+ "project": true,
+ "region": true,
+ "self_link": true,
+ "stateful_disk": [],
+ "status": true,
+ "update_policy": true,
+ "version": [
+ {
+ "instance_template": true,
+ "target_size": []
+ }
+ ]
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "auto_healing_policies": [],
+ "distribution_policy_zones": [
+ false,
+ false
+ ],
+ "named_port": [],
+ "stateful_disk": [],
+ "status": [],
+ "update_policy": [],
+ "version": [
+ {
+ "target_size": []
+ }
+ ]
+ }
+ }
+ },
+ {
+ "address": "google_compute_subnetwork.default",
+ "mode": "managed",
+ "type": "google_compute_subnetwork",
+ "name": "default",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "description": null,
+ "ip_cidr_range": "10.0.1.0/24",
+ "ipv6_access_type": null,
+ "log_config": [],
+ "name": "cbf-subnet",
+ "region": "europe-west9",
+ "role": null,
+ "timeouts": null
+ },
+ "after_unknown": {
+ "creation_timestamp": true,
+ "external_ipv6_prefix": true,
+ "fingerprint": true,
+ "gateway_address": true,
+ "id": true,
+ "ipv6_cidr_range": true,
+ "log_config": [],
+ "network": true,
+ "private_ip_google_access": true,
+ "private_ipv6_google_access": true,
+ "project": true,
+ "purpose": true,
+ "secondary_ip_range": true,
+ "self_link": true,
+ "stack_type": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "log_config": [],
+ "secondary_ip_range": []
+ }
+ }
+ },
+ {
+ "address": "google_sql_database_instance.instance",
+ "mode": "managed",
+ "type": "google_sql_database_instance",
+ "name": "instance",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "change": {
+ "actions": [
+ "create"
+ ],
+ "before": null,
+ "after": {
+ "clone": [],
+ "database_version": "POSTGRES_14",
+ "deletion_protection": true,
+ "name": "my-database-instance",
+ "region": "europe-west9",
+ "restore_backup_context": [],
+ "root_password": null,
+ "settings": [
+ {
+ "activation_policy": "ALWAYS",
+ "active_directory_config": [],
+ "availability_type": "REGIONAL",
+ "collation": null,
+ "database_flags": [],
+ "deletion_protection_enabled": null,
+ "deny_maintenance_period": [],
+ "disk_autoresize": true,
+ "disk_autoresize_limit": 0,
+ "disk_type": "PD_SSD",
+ "insights_config": [],
+ "maintenance_window": [],
+ "password_validation_policy": [],
+ "pricing_plan": "PER_USE",
+ "sql_server_audit_config": [],
+ "tier": "db-g1-small",
+ "time_zone": null
+ }
+ ],
+ "timeouts": null
+ },
+ "after_unknown": {
+ "available_maintenance_versions": true,
+ "clone": [],
+ "connection_name": true,
+ "encryption_key_name": true,
+ "first_ip_address": true,
+ "id": true,
+ "instance_type": true,
+ "ip_address": true,
+ "maintenance_version": true,
+ "master_instance_name": true,
+ "private_ip_address": true,
+ "project": true,
+ "public_ip_address": true,
+ "replica_configuration": true,
+ "restore_backup_context": [],
+ "self_link": true,
+ "server_ca_cert": true,
+ "service_account_email_address": true,
+ "settings": [
+ {
+ "active_directory_config": [],
+ "backup_configuration": true,
+ "connector_enforcement": true,
+ "database_flags": [],
+ "deny_maintenance_period": [],
+ "disk_size": true,
+ "insights_config": [],
+ "ip_configuration": true,
+ "location_preference": true,
+ "maintenance_window": [],
+ "password_validation_policy": [],
+ "sql_server_audit_config": [],
+ "user_labels": true,
+ "version": true
+ }
+ ]
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "available_maintenance_versions": [],
+ "clone": [],
+ "ip_address": [],
+ "replica_configuration": [],
+ "restore_backup_context": [],
+ "root_password": true,
+ "server_ca_cert": [],
+ "settings": [
+ {
+ "active_directory_config": [],
+ "backup_configuration": [],
+ "database_flags": [],
+ "deny_maintenance_period": [],
+ "insights_config": [],
+ "ip_configuration": [],
+ "location_preference": [],
+ "maintenance_window": [],
+ "password_validation_policy": [],
+ "sql_server_audit_config": [],
+ "user_labels": {}
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "prior_state": {
+ "format_version": "1.0",
+ "terraform_version": "1.3.7",
+ "values": {
+ "root_module": {
+ "resources": [
+ {
+ "address": "data.google_compute_image.debian",
+ "mode": "data",
+ "type": "google_compute_image",
+ "name": "debian",
+ "provider_name": "registry.terraform.io/hashicorp/google",
+ "schema_version": 0,
+ "values": {
+ "archive_size_bytes": 1675957440,
+ "creation_timestamp": "2023-02-06T09:16:17.455-08:00",
+ "description": "Debian, Debian GNU/Linux, 11 (bullseye), amd64 built on 20230206, supports Shielded VM features",
+ "disk_size_gb": 10,
+ "family": "debian-11",
+ "filter": null,
+ "id": "projects/debian-cloud/global/images/debian-11-bullseye-v20230206",
+ "image_encryption_key_sha256": "",
+ "image_id": "2681395124550535951",
+ "label_fingerprint": "42WmSpB8rSM=",
+ "labels": {},
+ "licenses": [
+ "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/licenses/debian-11-bullseye"
+ ],
+ "name": "debian-11-bullseye-v20230206",
+ "project": "debian-cloud",
+ "self_link": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20230206",
+ "source_disk": "",
+ "source_disk_encryption_key_sha256": "",
+ "source_disk_id": "",
+ "source_image_id": "",
+ "status": "READY"
+ },
+ "sensitive_values": {
+ "labels": {},
+ "licenses": [
+ false
+ ]
+ }
+ }
+ ]
+ }
+ }
+ },
+ "configuration": {
+ "provider_config": {
+ "google": {
+ "name": "google",
+ "full_name": "registry.terraform.io/hashicorp/google",
+ "expressions": {
+ "credentials": {},
+ "region": {
+ "constant_value": "europe-west9"
+ }
+ }
+ }
+ },
+ "root_module": {
+ "resources": [
+ {
+ "address": "google_compute_autoscaler.foobar",
+ "mode": "managed",
+ "type": "google_compute_autoscaler",
+ "name": "foobar",
+ "provider_config_key": "google",
+ "expressions": {
+ "autoscaling_policy": [
+ {
+ "cooldown_period": {
+ "constant_value": 60
+ },
+ "cpu_utilization": [
+ {
+ "target": {
+ "constant_value": 0.5
+ }
+ }
+ ],
+ "max_replicas": {
+ "constant_value": 10
+ },
+ "min_replicas": {
+ "constant_value": 1
+ }
+ }
+ ],
+ "name": {
+ "constant_value": "my-autoscaler"
+ },
+ "target": {
+ "references": [
+ "google_compute_region_instance_group_manager.my-group-manager.id",
+ "google_compute_region_instance_group_manager.my-group-manager"
+ ]
+ }
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "google_compute_disk.first",
+ "mode": "managed",
+ "type": "google_compute_disk",
+ "name": "first",
+ "provider_config_key": "google",
+ "expressions": {
+ "name": {
+ "constant_value": "cbf-disk-first"
+ },
+ "zone": {
+ "constant_value": "europe-west9-a"
+ }
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "google_compute_instance.default",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "default",
+ "provider_config_key": "google",
+ "expressions": {
+ "attached_disk": [
+ {
+ "source": {
+ "references": [
+ "google_compute_disk.first.self_link",
+ "google_compute_disk.first"
+ ]
+ }
+ }
+ ],
+ "boot_disk": [
+ {
+ "initialize_params": [
+ {
+ "image": {
+ "references": [
+ "data.google_compute_image.debian.self_link",
+ "data.google_compute_image.debian"
+ ]
+ },
+ "size": {
+ "constant_value": 564
+ }
+ }
+ ]
+ }
+ ],
+ "guest_accelerator": {
+ "constant_value": [
+ {
+ "count": 2,
+ "type": "nvidia-tesla-k80"
+ }
+ ]
+ },
+ "machine_type": {
+ "constant_value": "n1-standard-2"
+ },
+ "metadata_startup_script": {
+ "constant_value": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask"
+ },
+ "name": {
+ "constant_value": "cbf-test-vm"
+ },
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "subnetwork": {
+ "references": [
+ "google_compute_subnetwork.default.id",
+ "google_compute_subnetwork.default"
+ ]
+ }
+ }
+ ],
+ "tags": {
+ "constant_value": [
+ "ssh"
+ ]
+ },
+ "zone": {
+ "constant_value": "europe-west9-a"
+ }
+ },
+ "schema_version": 6,
+ "count_expression": {
+ "references": [
+ "var.instance_count"
+ ]
+ }
+ },
+ {
+ "address": "google_compute_instance.foo",
+ "mode": "managed",
+ "type": "google_compute_instance",
+ "name": "foo",
+ "provider_config_key": "google",
+ "expressions": {
+ "boot_disk": [
+ {
+ "initialize_params": [
+ {
+ "image": {
+ "constant_value": "debian-cloud/debian-11"
+ }
+ }
+ ]
+ }
+ ],
+ "machine_type": {
+ "constant_value": "n2-standard-2"
+ },
+ "metadata_startup_script": {
+ "constant_value": "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask"
+ },
+ "min_cpu_platform": {
+ "constant_value": "Intel Cascade Lake"
+ },
+ "name": {
+ "constant_value": "cbf-test-other"
+ },
+ "network_interface": [
+ {
+ "access_config": [
+ {}
+ ],
+ "subnetwork": {
+ "references": [
+ "google_compute_subnetwork.default.id",
+ "google_compute_subnetwork.default"
+ ]
+ }
+ }
+ ],
+ "tags": {
+ "constant_value": [
+ "ssh"
+ ]
+ },
+ "zone": {
+ "constant_value": "europe-west9-a"
+ }
+ },
+ "schema_version": 6,
+ "count_expression": {
+ "references": [
+ "var.instance_count"
+ ]
+ }
+ },
+ {
+ "address": "google_compute_instance_from_template.ifromtpl",
+ "mode": "managed",
+ "type": "google_compute_instance_from_template",
+ "name": "ifromtpl",
+ "provider_config_key": "google",
+ "expressions": {
+ "can_ip_forward": {
+ "constant_value": false
+ },
+ "labels": {
+ "constant_value": {
+ "my_key": "my_value"
+ }
+ },
+ "name": {
+ "constant_value": "instance-from-template"
+ },
+ "source_instance_template": {
+ "references": [
+ "google_compute_instance_template.my-instance-template.id",
+ "google_compute_instance_template.my-instance-template"
+ ]
+ },
+ "zone": {
+ "constant_value": "europe-west9-a"
+ }
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "google_compute_instance_template.my-instance-template",
+ "mode": "managed",
+ "type": "google_compute_instance_template",
+ "name": "my-instance-template",
+ "provider_config_key": "google",
+ "expressions": {
+ "disk": [
+ {
+ "boot": {
+ "constant_value": true
+ },
+ "disk_size_gb": {
+ "constant_value": 20
+ }
+ }
+ ],
+ "machine_type": {
+ "constant_value": "n2-standard-2"
+ },
+ "name": {
+ "constant_value": "my-instance-template"
+ },
+ "network_interface": [
+ {
+ "subnetwork": {
+ "references": [
+ "google_compute_subnetwork.default.id",
+ "google_compute_subnetwork.default"
+ ]
+ }
+ }
+ ]
+ },
+ "schema_version": 1
+ },
+ {
+ "address": "google_compute_network.vpc_network",
+ "mode": "managed",
+ "type": "google_compute_network",
+ "name": "vpc_network",
+ "provider_config_key": "google",
+ "expressions": {
+ "auto_create_subnetworks": {
+ "constant_value": false
+ },
+ "mtu": {
+ "constant_value": 1460
+ },
+ "name": {
+ "constant_value": "cbf-network"
+ }
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "google_compute_region_disk.second",
+ "mode": "managed",
+ "type": "google_compute_region_disk",
+ "name": "second",
+ "provider_config_key": "google",
+ "expressions": {
+ "name": {
+ "constant_value": "cbf-disk-second"
+ },
+ "replica_zones": {
+ "constant_value": [
+ "europe-west9-a",
+ "europe-west6-b"
+ ]
+ }
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "google_compute_region_instance_group_manager.my-group-manager",
+ "mode": "managed",
+ "type": "google_compute_region_instance_group_manager",
+ "name": "my-group-manager",
+ "provider_config_key": "google",
+ "expressions": {
+ "base_instance_name": {
+ "constant_value": "managed"
+ },
+ "distribution_policy_zones": {
+ "constant_value": [
+ "europe-west9-a",
+ "europe-west9-b"
+ ]
+ },
+ "name": {
+ "constant_value": "my-group-manager"
+ },
+ "target_size": {
+ "constant_value": 3
+ },
+ "version": [
+ {
+ "instance_template": {
+ "references": [
+ "google_compute_instance_template.my-instance-template.id",
+ "google_compute_instance_template.my-instance-template"
+ ]
+ }
+ }
+ ]
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "google_compute_subnetwork.default",
+ "mode": "managed",
+ "type": "google_compute_subnetwork",
+ "name": "default",
+ "provider_config_key": "google",
+ "expressions": {
+ "ip_cidr_range": {
+ "constant_value": "10.0.1.0/24"
+ },
+ "name": {
+ "constant_value": "cbf-subnet"
+ },
+ "network": {
+ "references": [
+ "google_compute_network.vpc_network.id",
+ "google_compute_network.vpc_network"
+ ]
+ },
+ "region": {
+ "constant_value": "europe-west9"
+ }
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "google_sql_database_instance.instance",
+ "mode": "managed",
+ "type": "google_sql_database_instance",
+ "name": "instance",
+ "provider_config_key": "google",
+ "expressions": {
+ "database_version": {
+ "constant_value": "POSTGRES_14"
+ },
+ "name": {
+ "constant_value": "my-database-instance"
+ },
+ "region": {
+ "constant_value": "europe-west9"
+ },
+ "settings": [
+ {
+ "availability_type": {
+ "constant_value": "REGIONAL"
+ },
+ "tier": {
+ "constant_value": "db-g1-small"
+ }
+ }
+ ]
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "data.google_compute_image.debian",
+ "mode": "data",
+ "type": "google_compute_image",
+ "name": "debian",
+ "provider_config_key": "google",
+ "expressions": {
+ "family": {
+ "constant_value": "debian-11"
+ },
+ "project": {
+ "constant_value": "debian-cloud"
+ }
+ },
+ "schema_version": 0
+ }
+ ],
+ "variables": {
+ "instance_count": {
+ "default": 2
+ }
+ }
+ }
+ },
+ "relevant_attributes": [
+ {
+ "resource": "data.google_compute_image.debian",
+ "attribute": [
+ "self_link"
+ ]
+ },
+ {
+ "resource": "google_compute_disk.first",
+ "attribute": [
+ "self_link"
+ ]
+ },
+ {
+ "resource": "google_compute_network.vpc_network",
+ "attribute": [
+ "id"
+ ]
+ },
+ {
+ "resource": "google_compute_subnetwork.default",
+ "attribute": [
+ "id"
+ ]
+ },
+ {
+ "resource": "google_compute_instance_template.my-instance-template",
+ "attribute": [
+ "id"
+ ]
+ },
+ {
+ "resource": "google_compute_region_instance_group_manager.my-group-manager",
+ "attribute": [
+ "id"
+ ]
+ }
+ ]
+}
diff --git a/test/terraform/planRaw/main.tf b/test/terraform/planRaw/main.tf
new file mode 100644
index 0000000..f2240d2
--- /dev/null
+++ b/test/terraform/planRaw/main.tf
@@ -0,0 +1,39 @@
+resource "google_compute_network" "vpc_network" {
+ name = "cbf-network"
+ auto_create_subnetworks = false
+ mtu = 1460
+}
+
+resource "google_compute_subnetwork" "first" {
+ name = "cbf-subnet"
+ ip_cidr_range = "10.0.1.0/24"
+ region = "europe-west9"
+ network = google_compute_network.vpc_network.id
+}
+
+resource "google_compute_instance" "first" {
+ name = "cbf-test-vm"
+ machine_type = var.machine_type
+ zone = "europe-west9-a"
+ tags = ["ssh"]
+
+ boot_disk {
+ initialize_params {
+ image = "debian-cloud/debian-11"
+ size = 567
+ type = "pd-balanced"
+ }
+ }
+
+ network_interface {
+ subnetwork = google_compute_subnetwork.first.id
+
+ access_config {
+ # Include this section to give the VM an external IP address
+ }
+ }
+}
+
+variable "machine_type" {
+ type = string
+}
\ No newline at end of file
diff --git a/test/terraform/planRaw/plan.tfplan b/test/terraform/planRaw/plan.tfplan
new file mode 100644
index 0000000..3df2e1f
Binary files /dev/null and b/test/terraform/planRaw/plan.tfplan differ
diff --git a/test/terraform/planRaw/provider.tf b/test/terraform/planRaw/provider.tf
new file mode 100644
index 0000000..7fb6a3d
--- /dev/null
+++ b/test/terraform/planRaw/provider.tf
@@ -0,0 +1,4 @@
+provider "google" {
+ region = "europe-west9"
+}
+