2015-07-10 22:08:49 +02:00
package terraform
import (
2018-09-05 23:35:30 +02:00
"errors"
2015-07-10 22:08:49 +02:00
"fmt"
"strings"
"testing"
2018-05-05 04:24:06 +02:00
"github.com/zclconf/go-cty/cty"
2018-05-11 23:52:29 +02:00
"github.com/hashicorp/terraform/addrs"
2018-07-05 19:33:29 +02:00
"github.com/hashicorp/terraform/configs/configschema"
2018-09-05 23:35:30 +02:00
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/provisioners"
"github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags"
2015-07-10 22:08:49 +02:00
)
2016-08-16 22:48:12 +02:00
func TestContext2Validate_badCount ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
2016-08-16 22:48:12 +02:00
m := testModule ( t , "validate-bad-count" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2016-08-16 22:48:12 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2016-08-16 22:48:12 +02:00
}
}
2020-06-02 15:01:12 +02:00
func TestContext2Validate_badResource_reference ( t * testing . T ) {
p := testProvider ( "aws" )
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
m := testModule ( t , "validate-bad-resource-count" )
c := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2016-08-16 22:48:12 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2016-08-16 22:48:12 +02:00
}
}
2015-07-10 22:08:49 +02:00
func TestContext2Validate_badVar ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
"num" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-bad-var" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2016-01-21 20:33:16 +01:00
}
}
2016-12-09 21:58:24 +01:00
func TestContext2Validate_varMapOverrideOld ( t * testing . T ) {
m := testModule ( t , "validate-module-pc-vars" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
2019-10-08 00:24:16 +02:00
_ , diags := NewContext ( & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2019-10-08 00:24:16 +02:00
Variables : InputValues { } ,
2016-12-09 21:58:24 +01:00
} )
2017-11-22 00:08:00 +01:00
if ! diags . HasErrors ( ) {
2019-10-08 00:24:16 +02:00
// Error should be: The input variable "provider_var" has not been assigned a value.
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2016-12-09 21:58:24 +01:00
}
}
2016-01-21 20:33:16 +01:00
func TestContext2Validate_varNoDefaultExplicitType ( t * testing . T ) {
m := testModule ( t , "validate-var-no-default-explicit-type" )
2019-10-08 00:24:16 +02:00
_ , diags := NewContext ( & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2016-01-21 20:33:16 +01:00
} )
2017-11-22 00:08:00 +01:00
if ! diags . HasErrors ( ) {
2019-10-08 00:24:16 +02:00
// Error should be: The input variable "maybe_a_map" has not been assigned a value.
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_computedVar ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"value" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
pt := testProvider ( "test" )
pt . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"test_instance" : {
Attributes : map [ string ] * configschema . Attribute {
2020-10-08 18:43:46 +02:00
"id" : { Type : cty . String , Computed : true } ,
2018-05-12 00:30:27 +02:00
"value" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-computed-var" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
addrs . NewDefaultProvider ( "test" ) : testProviderFuncFixed ( pt ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2020-10-08 18:43:46 +02:00
p . PrepareProviderConfigFn = func ( req providers . PrepareProviderConfigRequest ) ( resp providers . PrepareProviderConfigResponse ) {
val := req . Config . GetAttr ( "value" )
if val . IsKnown ( ) {
resp . Diagnostics = resp . Diagnostics . Append ( fmt . Errorf ( "value isn't computed" ) )
2015-07-10 22:08:49 +02:00
}
2020-10-08 18:43:46 +02:00
return
2015-07-10 22:08:49 +02:00
}
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
2020-10-08 18:26:12 +02:00
if p . ConfigureCalled {
t . Fatal ( "Configure should not be called for provider" )
}
2015-07-10 22:08:49 +02:00
}
2018-10-02 10:45:17 +02:00
func TestContext2Validate_computedInFunction ( t * testing . T ) {
p := testProvider ( "aws" )
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"attr" : { Type : cty . Number , Optional : true } ,
} ,
} ,
} ,
DataSources : map [ string ] * configschema . Block {
"aws_data_source" : {
Attributes : map [ string ] * configschema . Attribute {
"optional_attr" : { Type : cty . String , Optional : true } ,
"computed" : { Type : cty . String , Computed : true } ,
} ,
} ,
} ,
}
m := testModule ( t , "validate-computed-in-function" )
c := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-10-02 10:45:17 +02:00
} )
diags := c . Validate ( )
if diags . HasErrors ( ) {
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
}
}
2017-01-28 06:15:43 +01:00
// Test that validate allows through computed counts. We do this and allow
// them to fail during "plan" since we can't know if the computed values
// can be realized during a plan.
func TestContext2Validate_countComputed ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
DataSources : map [ string ] * configschema . Block {
"aws_data_source" : {
Attributes : map [ string ] * configschema . Attribute {
"compute" : { Type : cty . String , Optional : true } ,
"value" : { Type : cty . String , Computed : true } ,
} ,
} ,
} ,
}
2017-01-28 06:15:43 +01:00
m := testModule ( t , "validate-count-computed" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2017-01-28 06:15:43 +01:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2017-01-28 06:15:43 +01:00
}
}
2015-07-10 22:08:49 +02:00
func TestContext2Validate_countNegative ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-count-negative" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_countVariable ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "apply-count-variable" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_countVariableNoDefault ( t * testing . T ) {
p := testProvider ( "aws" )
m := testModule ( t , "validate-count-variable" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
2017-04-22 02:40:46 +02:00
} ,
2018-05-12 00:30:27 +02:00
} ,
2015-07-10 22:08:49 +02:00
}
2019-10-08 00:24:16 +02:00
_ , diags := NewContext ( & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
if ! diags . HasErrors ( ) {
2019-10-08 00:24:16 +02:00
// Error should be: The input variable "foo" has not been assigned a value.
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_moduleBadOutput ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-bad-module-output" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_moduleGood ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-good-module" )
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_moduleBadResource ( t * testing . T ) {
m := testModule ( t , "validate-module-bad-rc" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2021-01-09 21:33:38 +01:00
p . ValidateResourceTypeConfigResponse = & providers . ValidateResourceTypeConfigResponse {
2018-09-05 23:35:30 +02:00
Diagnostics : tfdiags . Diagnostics { } . Append ( fmt . Errorf ( "bad" ) ) ,
}
2015-07-10 22:08:49 +02:00
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_moduleDepsShouldNotCycle ( t * testing . T ) {
m := testModule ( t , "validate-module-deps-cycle" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"id" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
ctx := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_moduleProviderVar ( t * testing . T ) {
m := testModule ( t , "validate-module-pc-vars" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-05-05 04:24:06 +02:00
Variables : InputValues {
"provider_var" : & InputValue {
Value : cty . StringVal ( "bar" ) ,
SourceType : ValueFromCaller ,
} ,
2015-07-10 22:08:49 +02:00
} ,
} )
2020-10-08 18:43:46 +02:00
p . PrepareProviderConfigFn = func ( req providers . PrepareProviderConfigRequest ) ( resp providers . PrepareProviderConfigResponse ) {
if req . Config . GetAttr ( "foo" ) . IsNull ( ) {
resp . Diagnostics = resp . Diagnostics . Append ( errors . New ( "foo is null" ) )
}
return
2015-07-10 22:08:49 +02:00
}
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_moduleProviderInheritUnused ( t * testing . T ) {
m := testModule ( t , "validate-module-pc-inherit-unused" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2020-10-08 18:43:46 +02:00
p . PrepareProviderConfigFn = func ( req providers . PrepareProviderConfigRequest ) ( resp providers . PrepareProviderConfigResponse ) {
if req . Config . GetAttr ( "foo" ) . IsNull ( ) {
resp . Diagnostics = resp . Diagnostics . Append ( errors . New ( "foo is null" ) )
}
return
2015-07-10 22:08:49 +02:00
}
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_orphans ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
"num" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-good" )
2020-04-01 19:13:40 +02:00
state := states . NewState ( )
root := state . EnsureModule ( addrs . RootModuleInstance )
testSetResourceInstanceCurrent ( root , "aws_instance.web" , ` { "id":"bar"} ` , ` provider["registry.terraform.io/hashicorp/aws"] ` )
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
State : state ,
} )
2018-09-05 23:35:30 +02:00
p . ValidateResourceTypeConfigFn = func ( req providers . ValidateResourceTypeConfigRequest ) providers . ValidateResourceTypeConfigResponse {
var diags tfdiags . Diagnostics
if req . Config . GetAttr ( "foo" ) . IsNull ( ) {
2020-11-20 19:21:56 +01:00
diags = diags . Append ( errors . New ( "foo is not set" ) )
2018-09-05 23:35:30 +02:00
}
return providers . ValidateResourceTypeConfigResponse {
Diagnostics : diags ,
}
2015-07-10 22:08:49 +02:00
}
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_providerConfig_bad ( t * testing . T ) {
m := testModule ( t , "validate-bad-pc" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2021-01-09 21:33:38 +01:00
p . PrepareProviderConfigResponse = & providers . PrepareProviderConfigResponse {
2018-09-05 23:35:30 +02:00
Diagnostics : tfdiags . Diagnostics { } . Append ( fmt . Errorf ( "bad" ) ) ,
}
2015-07-10 22:08:49 +02:00
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if len ( diags ) != 1 {
t . Fatalf ( "wrong number of diagnostics %d; want %d" , len ( diags ) , 1 )
2015-07-10 22:08:49 +02:00
}
2017-11-22 00:08:00 +01:00
if ! strings . Contains ( diags . Err ( ) . Error ( ) , "bad" ) {
t . Fatalf ( "bad: %s" , diags . Err ( ) . Error ( ) )
2015-07-10 22:08:49 +02:00
}
}
2020-05-08 07:26:21 +02:00
func TestContext2Validate_providerConfig_skippedEmpty ( t * testing . T ) {
2020-12-06 18:35:35 +01:00
m := testModule ( t , "validate-skipped-pc-empty" )
2015-07-10 22:08:49 +02:00
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2021-01-09 21:33:38 +01:00
p . PrepareProviderConfigResponse = & providers . PrepareProviderConfigResponse {
2020-05-08 07:23:11 +02:00
Diagnostics : tfdiags . Diagnostics { } . Append ( fmt . Errorf ( "should not be called" ) ) ,
2018-09-05 23:35:30 +02:00
}
2015-07-10 22:08:49 +02:00
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
2020-05-08 07:23:11 +02:00
if diags . HasErrors ( ) {
2020-11-10 01:26:17 +01:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_providerConfig_good ( t * testing . T ) {
m := testModule ( t , "validate-bad-pc" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
2020-10-13 15:21:05 +02:00
// In this test there is a mismatch between the provider's fqn (hashicorp/test)
// and it's local name set in required_providers (arbitrary).
func TestContext2Validate_requiredProviderConfig ( t * testing . T ) {
m := testModule ( t , "validate-required-provider-config" )
p := testProvider ( "aws" )
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"required_attribute" : { Type : cty . String , Required : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute { } ,
2018-05-12 00:30:27 +02:00
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_provisionerConfig_bad ( t * testing . T ) {
m := testModule ( t , "validate-bad-prov-conf" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
pr := simpleMockProvisioner ( )
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2020-11-13 18:43:28 +01:00
Provisioners : map [ string ] provisioners . Factory {
2015-07-10 22:08:49 +02:00
"shell" : testProvisionerFuncFixed ( pr ) ,
} ,
} )
2021-01-09 21:33:38 +01:00
p . PrepareProviderConfigResponse = & providers . PrepareProviderConfigResponse {
2018-09-05 23:35:30 +02:00
Diagnostics : tfdiags . Diagnostics { } . Append ( fmt . Errorf ( "bad" ) ) ,
}
2015-07-10 22:08:49 +02:00
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
2019-03-26 14:11:43 +01:00
func TestContext2Validate_badResourceConnection ( t * testing . T ) {
m := testModule ( t , "validate-bad-resource-connection" )
p := testProvider ( "aws" )
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
pr := simpleMockProvisioner ( )
c := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2020-11-13 18:43:28 +01:00
Provisioners : map [ string ] provisioners . Factory {
2019-03-26 14:11:43 +01:00
"shell" : testProvisionerFuncFixed ( pr ) ,
} ,
} )
diags := c . Validate ( )
t . Log ( diags . Err ( ) )
if ! diags . HasErrors ( ) {
t . Fatalf ( "succeeded; want error" )
}
}
func TestContext2Validate_badProvisionerConnection ( t * testing . T ) {
m := testModule ( t , "validate-bad-prov-connection" )
p := testProvider ( "aws" )
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
pr := simpleMockProvisioner ( )
c := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2020-11-13 18:43:28 +01:00
Provisioners : map [ string ] provisioners . Factory {
2019-03-26 14:11:43 +01:00
"shell" : testProvisionerFuncFixed ( pr ) ,
} ,
} )
diags := c . Validate ( )
t . Log ( diags . Err ( ) )
if ! diags . HasErrors ( ) {
t . Fatalf ( "succeeded; want error" )
}
}
2015-07-10 22:08:49 +02:00
func TestContext2Validate_provisionerConfig_good ( t * testing . T ) {
m := testModule ( t , "validate-bad-prov-conf" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
Provider : & configschema . Block {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
pr := simpleMockProvisioner ( )
2018-09-05 23:35:30 +02:00
pr . ValidateProvisionerConfigFn = func ( req provisioners . ValidateProvisionerConfigRequest ) provisioners . ValidateProvisionerConfigResponse {
var diags tfdiags . Diagnostics
if req . Config . GetAttr ( "test_string" ) . IsNull ( ) {
2020-11-20 19:21:56 +01:00
diags = diags . Append ( errors . New ( "test_string is not set" ) )
2018-09-05 23:35:30 +02:00
}
return provisioners . ValidateProvisionerConfigResponse {
Diagnostics : diags ,
2015-07-10 22:08:49 +02:00
}
}
2018-05-12 00:30:27 +02:00
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2020-11-13 18:43:28 +01:00
Provisioners : map [ string ] provisioners . Factory {
2015-07-10 22:08:49 +02:00
"shell" : testProvisionerFuncFixed ( pr ) ,
} ,
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_requiredVar ( t * testing . T ) {
m := testModule ( t , "validate-required-var" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"ami" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2019-10-08 00:24:16 +02:00
_ , diags := NewContext ( & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
if ! diags . HasErrors ( ) {
2019-10-08 00:24:16 +02:00
// Error should be: The input variable "foo" has not been assigned a value.
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_resourceConfig_bad ( t * testing . T ) {
m := testModule ( t , "validate-bad-rc" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2021-01-09 21:33:38 +01:00
p . ValidateResourceTypeConfigResponse = & providers . ValidateResourceTypeConfigResponse {
2018-09-05 23:35:30 +02:00
Diagnostics : tfdiags . Diagnostics { } . Append ( fmt . Errorf ( "bad" ) ) ,
}
2015-07-10 22:08:49 +02:00
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if ! diags . HasErrors ( ) {
2018-05-12 00:30:27 +02:00
t . Fatalf ( "succeeded; want error" )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_resourceConfig_good ( t * testing . T ) {
m := testModule ( t , "validate-bad-rc" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
2017-04-22 02:40:46 +02:00
} ,
2018-05-12 00:30:27 +02:00
} ,
2015-07-10 22:08:49 +02:00
}
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
} )
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
2018-05-12 00:30:27 +02:00
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_tainted ( t * testing . T ) {
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
"num" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-good" )
2020-04-01 19:13:40 +02:00
state := states . NewState ( )
root := state . EnsureModule ( addrs . RootModuleInstance )
testSetResourceInstanceTainted ( root , "aws_instance.foo" , ` { "id":"bar"} ` , ` provider["registry.terraform.io/hashicorp/aws"] ` )
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2015-07-10 22:08:49 +02:00
State : state ,
} )
2018-09-05 23:35:30 +02:00
p . ValidateResourceTypeConfigFn = func ( req providers . ValidateResourceTypeConfigRequest ) providers . ValidateResourceTypeConfigResponse {
var diags tfdiags . Diagnostics
if req . Config . GetAttr ( "foo" ) . IsNull ( ) {
2020-11-20 19:21:56 +01:00
diags = diags . Append ( errors . New ( "foo is not set" ) )
2018-09-05 23:35:30 +02:00
}
return providers . ValidateResourceTypeConfigResponse {
Diagnostics : diags ,
}
2015-07-10 22:08:49 +02:00
}
2017-11-22 00:08:00 +01:00
diags := c . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
func TestContext2Validate_targetedDestroy ( t * testing . T ) {
m := testModule ( t , "validate-targeted" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
pr := simpleMockProvisioner ( )
2020-10-08 19:13:13 +02:00
p . ApplyResourceChangeFn = testApplyFn
p . PlanResourceChangeFn = testDiffFn
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
"num" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2020-04-01 19:13:40 +02:00
state := states . NewState ( )
root := state . EnsureModule ( addrs . RootModuleInstance )
testSetResourceInstanceCurrent ( root , "aws_instance.foo" , ` { "id":"i-bcd345"} ` , ` provider["registry.terraform.io/hashicorp/aws"] ` )
testSetResourceInstanceCurrent ( root , "aws_instance.bar" , ` { "id":"i-abc123"} ` , ` provider["registry.terraform.io/hashicorp/aws"] ` )
2015-07-10 22:08:49 +02:00
ctx := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2020-11-13 18:43:28 +01:00
Provisioners : map [ string ] provisioners . Factory {
2015-07-10 22:08:49 +02:00
"shell" : testProvisionerFuncFixed ( pr ) ,
} ,
2020-04-01 19:13:40 +02:00
State : state ,
2018-05-05 04:24:06 +02:00
Targets : [ ] addrs . Targetable {
addrs . RootModuleInstance . Resource (
addrs . ManagedResourceMode , "aws_instance" , "foo" ,
) ,
} ,
2015-07-10 22:08:49 +02:00
Destroy : true ,
} )
2017-11-22 00:08:00 +01:00
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2015-07-10 22:08:49 +02:00
}
}
2019-04-17 17:48:39 +02:00
func TestContext2Validate_varRefUnknown ( t * testing . T ) {
2015-07-10 22:08:49 +02:00
m := testModule ( t , "validate-variable-ref" )
p := testProvider ( "aws" )
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"foo" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2015-07-10 22:08:49 +02:00
c := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-05-05 04:24:06 +02:00
Variables : InputValues {
"foo" : & InputValue {
Value : cty . StringVal ( "bar" ) ,
SourceType : ValueFromCaller ,
} ,
2015-07-10 22:08:49 +02:00
} ,
} )
2018-09-05 23:35:30 +02:00
var value cty . Value
p . ValidateResourceTypeConfigFn = func ( req providers . ValidateResourceTypeConfigRequest ) providers . ValidateResourceTypeConfigResponse {
value = req . Config . GetAttr ( "foo" )
return providers . ValidateResourceTypeConfigResponse { }
2015-07-10 22:08:49 +02:00
}
c . Validate ( )
2019-04-17 17:48:39 +02:00
// Input variables are always unknown during the validate walk, because
// we're checking for validity of all possible input values. Validity
// against specific input values is checked during the plan walk.
if ! value . RawEquals ( cty . UnknownVal ( cty . String ) ) {
2015-07-10 22:08:49 +02:00
t . Fatalf ( "bad: %#v" , value )
}
}
2016-05-23 18:46:06 +02:00
// Module variables weren't being interpolated during Validate phase.
// related to https://github.com/hashicorp/terraform/issues/5322
func TestContext2Validate_interpolateVar ( t * testing . T ) {
input := new ( MockUIInput )
m := testModule ( t , "input-interpolate-var" )
p := testProvider ( "null" )
2020-10-08 19:13:13 +02:00
p . ApplyResourceChangeFn = testApplyFn
p . PlanResourceChangeFn = testDiffFn
2018-05-12 00:30:27 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"template_file" : {
Attributes : map [ string ] * configschema . Attribute {
"template" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2016-05-23 18:46:06 +02:00
ctx := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "template" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2016-05-23 18:46:06 +02:00
UIInput : input ,
} )
2017-11-22 00:08:00 +01:00
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2016-05-23 18:46:06 +02:00
}
}
2016-05-23 22:54:14 +02:00
// When module vars reference something that is actually computed, this
// shouldn't cause validation to fail.
func TestContext2Validate_interpolateComputedModuleVarDef ( t * testing . T ) {
input := new ( MockUIInput )
m := testModule ( t , "validate-computed-module-var-ref" )
p := testProvider ( "aws" )
2020-10-08 19:13:13 +02:00
p . ApplyResourceChangeFn = testApplyFn
p . PlanResourceChangeFn = testDiffFn
2018-05-11 23:52:29 +02:00
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"aws_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"attr" : { Type : cty . String , Optional : true } ,
} ,
} ,
} ,
}
2016-05-23 22:54:14 +02:00
ctx := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2016-05-23 22:54:14 +02:00
UIInput : input ,
} )
2017-11-22 00:08:00 +01:00
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2016-05-23 22:54:14 +02:00
}
}
2016-10-26 22:05:50 +02:00
// Computed values are lost when a map is output from a module
func TestContext2Validate_interpolateMap ( t * testing . T ) {
input := new ( MockUIInput )
m := testModule ( t , "issue-9549" )
2018-06-01 20:06:25 +02:00
p := testProvider ( "template" )
2020-10-08 19:13:13 +02:00
p . ApplyResourceChangeFn = testApplyFn
p . PlanResourceChangeFn = testDiffFn
2016-10-26 22:05:50 +02:00
ctx := testContext2 ( t , & ContextOpts {
2018-05-05 04:24:06 +02:00
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "template" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2016-10-26 22:05:50 +02:00
UIInput : input ,
} )
2017-11-22 00:08:00 +01:00
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
2018-05-11 23:52:29 +02:00
t . Fatalf ( "unexpected error: %s" , diags . Err ( ) )
2016-10-26 22:05:50 +02:00
}
}
2016-12-02 16:53:29 +01:00
2020-11-20 16:58:40 +01:00
func TestContext2Validate_varSensitive ( t * testing . T ) {
// Smoke test through validate where a variable has sensitive applied
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
variable "foo" {
default = "xyz"
sensitive = true
}
variable "bar" {
sensitive = true
}
data "aws_data_source" "bar" {
foo = var . bar
}
resource "aws_instance" "foo" {
foo = var . foo
}
` ,
} )
p := testProvider ( "aws" )
p . ValidateResourceTypeConfigFn = func ( req providers . ValidateResourceTypeConfigRequest ) providers . ValidateResourceTypeConfigResponse {
// Providers receive unmarked values
if got , want := req . Config . GetAttr ( "foo" ) , cty . UnknownVal ( cty . String ) ; ! got . RawEquals ( want ) {
t . Fatalf ( "wrong value for foo\ngot: %#v\nwant: %#v" , got , want )
}
return providers . ValidateResourceTypeConfigResponse { }
}
p . ValidateDataSourceConfigFn = func ( req providers . ValidateDataSourceConfigRequest ) ( resp providers . ValidateDataSourceConfigResponse ) {
if got , want := req . Config . GetAttr ( "foo" ) , cty . UnknownVal ( cty . String ) ; ! got . RawEquals ( want ) {
t . Fatalf ( "wrong value for foo\ngot: %#v\nwant: %#v" , got , want )
}
return providers . ValidateDataSourceConfigResponse { }
}
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
Providers : map [ addrs . Provider ] providers . Factory {
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
} ,
Variables : InputValues {
"bar" : & InputValue {
Value : cty . StringVal ( "boop" ) ,
SourceType : ValueFromCaller ,
} ,
} ,
} )
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
t . Fatal ( diags . Err ( ) )
}
if ! p . ValidateResourceTypeConfigCalled {
t . Fatal ( "expected ValidateResourceTypeConfigFn to be called" )
}
if ! p . ValidateDataSourceConfigCalled {
t . Fatal ( "expected ValidateDataSourceConfigFn to be called" )
}
}
2016-12-02 16:53:29 +01:00
// Manually validate using the new PlanGraphBuilder
func TestContext2Validate_PlanGraphBuilder ( t * testing . T ) {
2018-05-11 23:40:40 +02:00
fixture := contextFixtureApplyVars ( t )
opts := fixture . ContextOpts ( )
opts . Variables = InputValues {
"foo" : & InputValue {
Value : cty . StringVal ( "us-east-1" ) ,
SourceType : ValueFromCaller ,
2016-12-02 16:53:29 +01:00
} ,
2018-05-11 23:40:40 +02:00
"test_list" : & InputValue {
Value : cty . ListVal ( [ ] cty . Value {
cty . StringVal ( "Hello" ) ,
cty . StringVal ( "World" ) ,
} ) ,
SourceType : ValueFromCaller ,
} ,
"test_map" : & InputValue {
Value : cty . MapVal ( map [ string ] cty . Value {
"Hello" : cty . StringVal ( "World" ) ,
"Foo" : cty . StringVal ( "Bar" ) ,
"Baz" : cty . StringVal ( "Foo" ) ,
} ) ,
SourceType : ValueFromCaller ,
} ,
"amis" : & InputValue {
Value : cty . MapVal ( map [ string ] cty . Value {
"us-east-1" : cty . StringVal ( "override" ) ,
} ) ,
SourceType : ValueFromCaller ,
} ,
}
c := testContext2 ( t , opts )
2016-12-02 16:53:29 +01:00
2018-05-05 04:24:06 +02:00
graph , diags := ( & PlanGraphBuilder {
Config : c . config ,
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
State : states . NewState ( ) ,
2018-05-05 04:24:06 +02:00
Components : c . components ,
2018-05-31 21:39:45 +02:00
Schemas : c . schemas ,
2018-05-05 04:24:06 +02:00
Targets : c . targets ,
} ) . Build ( addrs . RootModuleInstance )
if diags . HasErrors ( ) {
t . Fatalf ( "errors from PlanGraphBuilder: %s" , diags . Err ( ) )
2017-07-20 11:23:43 +02:00
}
2017-01-30 17:41:38 +01:00
defer c . acquireRun ( "validate-test" ) ( )
2018-05-05 04:24:06 +02:00
walker , diags := c . walk ( graph , walkValidate )
if diags . HasErrors ( ) {
t . Fatal ( diags . Err ( ) )
2016-12-02 16:53:29 +01:00
}
2018-05-05 04:24:06 +02:00
if len ( walker . NonFatalDiagnostics ) > 0 {
t . Fatal ( walker . NonFatalDiagnostics . Err ( ) )
2016-12-02 16:53:29 +01:00
}
}
2018-05-22 20:16:08 +02:00
func TestContext2Validate_invalidOutput ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
data "aws_data_source" "name" { }
output "out" {
value = "${data.aws_data_source.name.missing}"
} ` ,
} )
p := testProvider ( "aws" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-05-22 20:16:08 +02:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
2018-11-21 02:25:05 +01:00
// Should get this error:
// Unsupported attribute: This object does not have an attribute named "missing"
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , "Unsupported attribute" ; ! strings . Contains ( got , want ) {
2018-11-21 02:25:05 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
2018-05-22 20:16:08 +02:00
}
func TestContext2Validate_invalidModuleOutput ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"child/main.tf" : `
data "aws_data_source" "name" { }
output "out" {
value = "${data.aws_data_source.name.missing}"
} ` ,
"main.tf" : `
module "child" {
source = "./child"
}
resource "aws_instance" "foo" {
foo = "${module.child.out}"
} ` ,
} )
p := testProvider ( "aws" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-05-22 20:16:08 +02:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
2018-11-21 02:25:05 +01:00
// Should get this error:
// Unsupported attribute: This object does not have an attribute named "missing"
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , "Unsupported attribute" ; ! strings . Contains ( got , want ) {
2018-11-21 02:25:05 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
2020-11-05 22:02:40 +01:00
func TestContext2Validate_invalidSensitiveModuleOutput ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"child/main.tf" : `
variable "foo" {
default = "xyz"
sensitive = true
}
output "out" {
value = var . foo
} ` ,
"main.tf" : `
module "child" {
source = "./child"
}
resource "aws_instance" "foo" {
foo = module . child . out
} ` ,
} )
p := testProvider ( "aws" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
Providers : map [ addrs . Provider ] providers . Factory {
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
} ,
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
// Should get this error:
// Output refers to sensitive values: Expressions used in outputs can only refer to sensitive values if the sensitive attribute is true.
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , "Output refers to sensitive values" ; ! strings . Contains ( got , want ) {
2018-11-21 02:25:05 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
func TestContext2Validate_legacyResourceCount ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
resource "aws_instance" "test" { }
output "out" {
value = aws_instance . test . count
} ` ,
} )
p := testProvider ( "aws" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-11-21 02:25:05 +01:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
// Should get this error:
// Invalid resource count attribute: The special "count" attribute is no longer supported after Terraform v0.12. Instead, use length(aws_instance.test) to count resource instances.
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , "Invalid resource count attribute:" ; ! strings . Contains ( got , want ) {
2018-11-21 02:25:05 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
2018-05-22 20:16:08 +02:00
}
2018-11-28 20:25:44 +01:00
func TestContext2Validate_invalidModuleRef ( t * testing . T ) {
// This test is verifying that we properly validate and report on references
// to modules that are not declared, since we were missing some validation
// here in early 0.12.0 alphas that led to a panic.
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
output "out" {
# Intentionally referencing undeclared module to ensure error
value = module . foo
} ` ,
} )
p := testProvider ( "aws" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-11-28 20:25:44 +01:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
// Should get this error:
// Reference to undeclared module: No module call named "foo" is declared in the root module.
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , "Reference to undeclared module:" ; ! strings . Contains ( got , want ) {
2018-11-28 20:25:44 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
func TestContext2Validate_invalidModuleOutputRef ( t * testing . T ) {
// This test is verifying that we properly validate and report on references
// to modules that are not declared, since we were missing some validation
// here in early 0.12.0 alphas that led to a panic.
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
output "out" {
# Intentionally referencing undeclared module to ensure error
value = module . foo . bar
} ` ,
} )
p := testProvider ( "aws" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-11-28 20:25:44 +01:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
// Should get this error:
// Reference to undeclared module: No module call named "foo" is declared in the root module.
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , "Reference to undeclared module:" ; ! strings . Contains ( got , want ) {
2018-11-28 20:25:44 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
2018-12-15 02:14:17 +01:00
func TestContext2Validate_invalidDependsOnResourceRef ( t * testing . T ) {
// This test is verifying that we raise an error if depends_on
// refers to something that doesn't exist in configuration.
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
resource "test_instance" "bar" {
depends_on = [ test_resource . nonexistant ]
}
` ,
} )
p := testProvider ( "test" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "test" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-12-15 02:14:17 +01:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
// Should get this error:
// Reference to undeclared module: No module call named "foo" is declared in the root module.
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , "Reference to undeclared resource:" ; ! strings . Contains ( got , want ) {
2018-12-15 02:14:17 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
func TestContext2Validate_invalidResourceIgnoreChanges ( t * testing . T ) {
// This test is verifying that we raise an error if ignore_changes
// refers to something that can be statically detected as not conforming
// to the resource type schema.
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
resource "test_instance" "bar" {
lifecycle {
ignore_changes = [ does_not_exist_in_schema ]
}
}
` ,
} )
p := testProvider ( "test" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "test" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2018-12-15 02:14:17 +01:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
// Should get this error:
// Reference to undeclared module: No module call named "foo" is declared in the root module.
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , ` no argument, nested block, or exported attribute named "does_not_exist_in_schema" ` ; ! strings . Contains ( got , want ) {
2018-12-15 02:14:17 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
2020-01-04 02:12:49 +01:00
func TestContext2Validate_variableCustomValidationsFail ( t * testing . T ) {
// This test is for custom validation rules associated with root module
// variables, and specifically that we handle the situation where the
// given value is invalid in a child module.
m := testModule ( t , "validate-variable-custom-validations-child" )
p := testProvider ( "test" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "test" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2020-01-04 02:12:49 +01:00
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , ` Invalid value for variable: Value must not be "nope". ` ; ! strings . Contains ( got , want ) {
2020-01-04 02:12:49 +01:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
func TestContext2Validate_variableCustomValidationsRoot ( t * testing . T ) {
// This test is for custom validation rules associated with root module
// variables, and specifically that we handle the situation where their
// values are unknown during validation, skipping the validation check
// altogether. (Root module variables are never known during validation.)
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
variable "test" {
type = string
validation {
condition = var . test != "nope"
error_message = "Value must not be \"nope\"."
}
}
` ,
} )
p := testProvider ( "test" )
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-03-31 20:03:33 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
2020-04-01 19:13:40 +02:00
addrs . NewDefaultProvider ( "test" ) : testProviderFuncFixed ( p ) ,
2020-03-31 20:03:33 +02:00
} ,
2020-01-04 02:12:49 +01:00
Variables : InputValues {
"test" : & InputValue {
Value : cty . UnknownVal ( cty . String ) ,
SourceType : ValueFromCLIArg ,
} ,
} ,
} )
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
t . Fatalf ( "unexpected error\ngot: %s" , diags . Err ( ) . Error ( ) )
}
}
2020-04-05 17:17:28 +02:00
func TestContext2Validate_expandModules ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
module "mod1" {
for_each = toset ( [ "a" , "b" ] )
source = "./mod"
}
module "mod2" {
for_each = module . mod1
source = "./mod"
2020-04-17 18:36:17 +02:00
input = module . mod1 [ "a" ] . out
2020-04-05 17:17:28 +02:00
}
module "mod3" {
2020-05-05 22:44:22 +02:00
count = length ( module . mod2 )
2020-04-05 17:17:28 +02:00
source = "./mod"
}
` ,
"mod/main.tf" : `
resource "aws_instance" "foo" {
}
2020-04-17 18:36:17 +02:00
output "out" {
value = 1
}
variable "input" {
type = number
default = 0
}
2020-04-05 17:17:28 +02:00
module "nested" {
count = 2
source = "./nested"
2020-04-08 01:30:18 +02:00
input = count . index
2020-04-05 17:17:28 +02:00
}
` ,
"mod/nested/main.tf" : `
variable "input" {
}
resource "aws_instance" "foo" {
count = var . input
}
` ,
} )
p := testProvider ( "aws" )
2020-10-08 19:13:13 +02:00
p . PlanResourceChangeFn = testDiffFn
2020-04-05 17:17:28 +02:00
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
2020-04-06 18:50:37 +02:00
Providers : map [ addrs . Provider ] providers . Factory {
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
} ,
2020-04-05 17:17:28 +02:00
} )
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
t . Fatal ( diags . ErrWithWarnings ( ) )
}
}
2020-05-05 22:44:22 +02:00
func TestContext2Validate_expandModulesInvalidCount ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
module "mod1" {
count = - 1
source = "./mod"
}
` ,
"mod/main.tf" : `
resource "aws_instance" "foo" {
}
` ,
} )
p := testProvider ( "aws" )
2020-10-08 19:13:13 +02:00
p . PlanResourceChangeFn = testDiffFn
2020-05-05 22:44:22 +02:00
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
Providers : map [ addrs . Provider ] providers . Factory {
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
} ,
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , ` Invalid count argument ` ; ! strings . Contains ( got , want ) {
2020-05-05 22:44:22 +02:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
func TestContext2Validate_expandModulesInvalidForEach ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
module "mod1" {
for_each = [ "a" , "b" ]
source = "./mod"
}
` ,
"mod/main.tf" : `
resource "aws_instance" "foo" {
}
` ,
} )
p := testProvider ( "aws" )
2020-10-08 19:13:13 +02:00
p . PlanResourceChangeFn = testDiffFn
2020-05-05 22:44:22 +02:00
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
Providers : map [ addrs . Provider ] providers . Factory {
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
} ,
} )
diags := ctx . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
2020-12-01 21:51:54 +01:00
if got , want := diags . Err ( ) . Error ( ) , ` Invalid for_each argument ` ; ! strings . Contains ( got , want ) {
2020-05-05 22:44:22 +02:00
t . Fatalf ( "wrong error:\ngot: %s\nwant: message containing %q" , got , want )
}
}
2020-06-07 03:27:29 +02:00
func TestContext2Validate_expandMultipleNestedModules ( t * testing . T ) {
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
module "modA" {
for_each = {
first = "m"
second = "n"
}
source = "./modA"
}
` ,
"modA/main.tf" : `
locals {
m = {
first = "m"
second = "n"
}
}
module "modB" {
for_each = local . m
source = "./modB"
y = each . value
}
module "modC" {
for_each = local . m
source = "./modC"
x = module . modB [ each . key ] . out
y = module . modB [ each . key ] . out
}
` ,
"modA/modB/main.tf" : `
variable "y" {
type = string
}
resource "aws_instance" "foo" {
foo = var . y
}
output "out" {
value = aws_instance . foo . id
}
` ,
"modA/modC/main.tf" : `
variable "x" {
type = string
}
variable "y" {
type = string
}
resource "aws_instance" "foo" {
foo = var . x
}
output "out" {
value = var . y
}
` ,
} )
p := testProvider ( "aws" )
2020-10-08 19:13:13 +02:00
p . PlanResourceChangeFn = testDiffFn
2020-06-07 03:27:29 +02:00
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
Providers : map [ addrs . Provider ] providers . Factory {
addrs . NewDefaultProvider ( "aws" ) : testProviderFuncFixed ( p ) ,
} ,
} )
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
t . Fatal ( diags . ErrWithWarnings ( ) )
}
}
2020-06-16 19:17:21 +02:00
func TestContext2Validate_invalidModuleDependsOn ( t * testing . T ) {
// validate module and output depends_on
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
module "mod1" {
source = "./mod"
depends_on = [ resource_foo . bar . baz ]
}
module "mod2" {
source = "./mod"
depends_on = [ resource_foo . bar . baz ]
}
` ,
"mod/main.tf" : `
output "out" {
value = "foo"
}
` ,
} )
diags := testContext2 ( t , & ContextOpts {
Config : m ,
} ) . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
if len ( diags ) != 2 {
t . Fatalf ( "wanted 2 diagnostic errors, got %q" , diags )
}
for _ , d := range diags {
des := d . Description ( ) . Summary
if ! strings . Contains ( des , "Invalid depends_on reference" ) {
t . Fatalf ( ` expected "Invalid depends_on reference", got %q ` , des )
}
}
}
func TestContext2Validate_invalidOutputDependsOn ( t * testing . T ) {
// validate module and output depends_on
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
module "mod1" {
source = "./mod"
}
output "out" {
value = "bar"
depends_on = [ resource_foo . bar . baz ]
}
` ,
"mod/main.tf" : `
output "out" {
value = "bar"
depends_on = [ resource_foo . bar . baz ]
}
` ,
} )
diags := testContext2 ( t , & ContextOpts {
Config : m ,
} ) . Validate ( )
if ! diags . HasErrors ( ) {
t . Fatal ( "succeeded; want errors" )
}
if len ( diags ) != 2 {
t . Fatalf ( "wanted 2 diagnostic errors, got %q" , diags )
}
for _ , d := range diags {
des := d . Description ( ) . Summary
if ! strings . Contains ( des , "Invalid depends_on reference" ) {
t . Fatalf ( ` expected "Invalid depends_on reference", got %q ` , des )
}
}
}
2020-09-25 22:59:58 +02:00
2020-10-28 19:51:04 +01:00
func TestContext2Validate_rpcDiagnostics ( t * testing . T ) {
// validate module and output depends_on
m := testModuleInline ( t , map [ string ] string {
"main.tf" : `
resource "test_instance" "a" {
}
` ,
} )
p := testProvider ( "test" )
p . GetSchemaReturn = & ProviderSchema {
ResourceTypes : map [ string ] * configschema . Block {
"test_instance" : {
Attributes : map [ string ] * configschema . Attribute {
"id" : { Type : cty . String , Computed : true } ,
} ,
} ,
} ,
}
2021-01-09 21:33:38 +01:00
p . ValidateResourceTypeConfigResponse = & providers . ValidateResourceTypeConfigResponse {
2020-10-28 19:51:04 +01:00
Diagnostics : tfdiags . Diagnostics ( nil ) . Append ( tfdiags . SimpleWarning ( "don't frobble" ) ) ,
}
ctx := testContext2 ( t , & ContextOpts {
Config : m ,
Providers : map [ addrs . Provider ] providers . Factory {
addrs . NewDefaultProvider ( "test" ) : testProviderFuncFixed ( p ) ,
} ,
} )
diags := ctx . Validate ( )
if diags . HasErrors ( ) {
t . Fatal ( diags . Err ( ) )
}
2020-10-28 22:38:01 +01:00
if len ( diags ) == 0 {
t . Fatal ( "expected warnings" )
}
2020-10-28 19:51:04 +01:00
for _ , d := range diags {
des := d . Description ( ) . Summary
if ! strings . Contains ( des , "frobble" ) {
t . Fatalf ( ` expected frobble, got %q ` , des )
}
}
}