github.com/opentofu/opentofu@v1.7.1/internal/cloud/cloud_variables_test.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package cloud
     7  
     8  import (
     9  	"testing"
    10  
    11  	"github.com/google/go-cmp/cmp"
    12  	"github.com/hashicorp/hcl/v2"
    13  	"github.com/opentofu/opentofu/internal/backend"
    14  	"github.com/opentofu/opentofu/internal/configs"
    15  	"github.com/opentofu/opentofu/internal/tfdiags"
    16  	"github.com/opentofu/opentofu/internal/tofu"
    17  	"github.com/zclconf/go-cty/cty"
    18  )
    19  
    20  func TestParseCloudRunVariables(t *testing.T) {
    21  	t.Run("populates variables from allowed sources", func(t *testing.T) {
    22  		vv := map[string]backend.UnparsedVariableValue{
    23  			"undeclared":                      testUnparsedVariableValue{source: tofu.ValueFromCLIArg, value: cty.StringVal("0")},
    24  			"declaredFromConfig":              testUnparsedVariableValue{source: tofu.ValueFromConfig, value: cty.StringVal("1")},
    25  			"declaredFromNamedFileMapString":  testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.MapVal(map[string]cty.Value{"foo": cty.StringVal("bar")})},
    26  			"declaredFromNamedFileBool":       testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.BoolVal(true)},
    27  			"declaredFromNamedFileNumber":     testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.NumberIntVal(2)},
    28  			"declaredFromNamedFileListString": testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.ListVal([]cty.Value{cty.StringVal("2a"), cty.StringVal("2b")})},
    29  			"declaredFromNamedFileNull":       testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.NullVal(cty.String)},
    30  			"declaredFromNamedMapComplex":     testUnparsedVariableValue{source: tofu.ValueFromNamedFile, value: cty.MapVal(map[string]cty.Value{"foo": cty.ObjectVal(map[string]cty.Value{"qux": cty.ListVal([]cty.Value{cty.BoolVal(true), cty.BoolVal(false)})})})},
    31  			"declaredFromCLIArg":              testUnparsedVariableValue{source: tofu.ValueFromCLIArg, value: cty.StringVal("3")},
    32  			"declaredFromEnvVar":              testUnparsedVariableValue{source: tofu.ValueFromEnvVar, value: cty.StringVal("4")},
    33  		}
    34  
    35  		decls := map[string]*configs.Variable{
    36  			"declaredFromConfig": {
    37  				Name:           "declaredFromConfig",
    38  				Type:           cty.String,
    39  				ConstraintType: cty.String,
    40  				ParsingMode:    configs.VariableParseLiteral,
    41  				DeclRange: hcl.Range{
    42  					Filename: "fake.tf",
    43  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
    44  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
    45  				},
    46  			},
    47  			"declaredFromNamedFileMapString": {
    48  				Name:           "declaredFromNamedFileMapString",
    49  				Type:           cty.Map(cty.String),
    50  				ConstraintType: cty.Map(cty.String),
    51  				ParsingMode:    configs.VariableParseHCL,
    52  				DeclRange: hcl.Range{
    53  					Filename: "fake.tf",
    54  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
    55  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
    56  				},
    57  			},
    58  			"declaredFromNamedFileBool": {
    59  				Name:           "declaredFromNamedFileBool",
    60  				Type:           cty.Bool,
    61  				ConstraintType: cty.Bool,
    62  				ParsingMode:    configs.VariableParseLiteral,
    63  				DeclRange: hcl.Range{
    64  					Filename: "fake.tf",
    65  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
    66  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
    67  				},
    68  			},
    69  			"declaredFromNamedFileNumber": {
    70  				Name:           "declaredFromNamedFileNumber",
    71  				Type:           cty.Number,
    72  				ConstraintType: cty.Number,
    73  				ParsingMode:    configs.VariableParseLiteral,
    74  				DeclRange: hcl.Range{
    75  					Filename: "fake.tf",
    76  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
    77  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
    78  				},
    79  			},
    80  			"declaredFromNamedFileListString": {
    81  				Name:           "declaredFromNamedFileListString",
    82  				Type:           cty.List(cty.String),
    83  				ConstraintType: cty.List(cty.String),
    84  				ParsingMode:    configs.VariableParseHCL,
    85  				DeclRange: hcl.Range{
    86  					Filename: "fake.tf",
    87  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
    88  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
    89  				},
    90  			},
    91  			"declaredFromNamedFileNull": {
    92  				Name:           "declaredFromNamedFileNull",
    93  				Type:           cty.String,
    94  				ConstraintType: cty.String,
    95  				ParsingMode:    configs.VariableParseHCL,
    96  				DeclRange: hcl.Range{
    97  					Filename: "fake.tf",
    98  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
    99  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
   100  				},
   101  			},
   102  			"declaredFromNamedMapComplex": {
   103  				Name:           "declaredFromNamedMapComplex",
   104  				Type:           cty.DynamicPseudoType,
   105  				ConstraintType: cty.DynamicPseudoType,
   106  				ParsingMode:    configs.VariableParseHCL,
   107  				DeclRange: hcl.Range{
   108  					Filename: "fake.tf",
   109  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
   110  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
   111  				},
   112  			},
   113  			"declaredFromCLIArg": {
   114  				Name:           "declaredFromCLIArg",
   115  				Type:           cty.String,
   116  				ConstraintType: cty.String,
   117  				ParsingMode:    configs.VariableParseLiteral,
   118  				DeclRange: hcl.Range{
   119  					Filename: "fake.tf",
   120  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
   121  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
   122  				},
   123  			},
   124  			"declaredFromEnvVar": {
   125  				Name:           "declaredFromEnvVar",
   126  				Type:           cty.String,
   127  				ConstraintType: cty.String,
   128  				ParsingMode:    configs.VariableParseLiteral,
   129  				DeclRange: hcl.Range{
   130  					Filename: "fake.tf",
   131  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
   132  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
   133  				},
   134  			},
   135  			"missing": {
   136  				Name:           "missing",
   137  				Type:           cty.String,
   138  				ConstraintType: cty.String,
   139  				Default:        cty.StringVal("2"),
   140  				ParsingMode:    configs.VariableParseLiteral,
   141  				DeclRange: hcl.Range{
   142  					Filename: "fake.tf",
   143  					Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
   144  					End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
   145  				},
   146  			},
   147  		}
   148  		wantVals := make(map[string]string)
   149  		wantVals["declaredFromNamedFileBool"] = "true"
   150  		wantVals["declaredFromNamedFileNumber"] = "2"
   151  		wantVals["declaredFromNamedFileListString"] = `["2a", "2b"]`
   152  		wantVals["declaredFromNamedFileNull"] = "null"
   153  		wantVals["declaredFromNamedFileMapString"] = "{\n  foo = \"bar\"\n}"
   154  		wantVals["declaredFromNamedMapComplex"] = "{\n  foo = {\n    qux = [true, false]\n  }\n}"
   155  		wantVals["declaredFromCLIArg"] = `"3"`
   156  		wantVals["declaredFromEnvVar"] = `"4"`
   157  
   158  		gotVals, diags := ParseCloudRunVariables(vv, decls)
   159  		if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" {
   160  			t.Errorf("wrong result\n%s", diff)
   161  		}
   162  
   163  		if got, want := len(diags), 1; got != want {
   164  			t.Fatalf("expected 1 variable error: %v, got %v", diags.Err(), want)
   165  		}
   166  
   167  		if got, want := diags[0].Description().Summary, "Value for undeclared variable"; got != want {
   168  			t.Errorf("wrong summary for diagnostic 0\ngot:  %s\nwant: %s", got, want)
   169  		}
   170  	})
   171  }
   172  
   173  type testUnparsedVariableValue struct {
   174  	source tofu.ValueSourceType
   175  	value  cty.Value
   176  }
   177  
   178  func (v testUnparsedVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*tofu.InputValue, tfdiags.Diagnostics) {
   179  	return &tofu.InputValue{
   180  		Value:      v.value,
   181  		SourceType: v.source,
   182  		SourceRange: tfdiags.SourceRange{
   183  			Filename: "fake.tfvars",
   184  			Start:    tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
   185  			End:      tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
   186  		},
   187  	}, nil
   188  }