diff --git a/docs/resources/secret_with_authorization_code_grant.md b/docs/resources/secret_with_authorization_code_grant.md
index 5042b86916..ff13b763fc 100644
--- a/docs/resources/secret_with_authorization_code_grant.md
+++ b/docs/resources/secret_with_authorization_code_grant.md
@@ -59,6 +59,7 @@ resource "snowflake_secret_with_authorization_code_grant" "test" {
- `describe_output` (List of Object) Outputs the result of `DESCRIBE SECRET` for the given secret. (see [below for nested schema](#nestedatt--describe_output))
- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
+- `secret_type` (String) Specifies a type for the secret. This field is used for checking external changes and recreating the resources if needed.
- `show_output` (List of Object) Outputs the result of `SHOW SECRETS` for the given secret. (see [below for nested schema](#nestedatt--show_output))
diff --git a/docs/resources/secret_with_basic_authentication.md b/docs/resources/secret_with_basic_authentication.md
index 6192ae72be..e7078451d4 100644
--- a/docs/resources/secret_with_basic_authentication.md
+++ b/docs/resources/secret_with_basic_authentication.md
@@ -56,6 +56,7 @@ resource "snowflake_secret_with_basic_authentication" "test" {
- `describe_output` (List of Object) Outputs the result of `DESCRIBE SECRET` for the given secret. (see [below for nested schema](#nestedatt--describe_output))
- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
+- `secret_type` (String) Specifies a type for the secret. This field is used for checking external changes and recreating the resources if needed.
- `show_output` (List of Object) Outputs the result of `SHOW SECRETS` for the given secret. (see [below for nested schema](#nestedatt--show_output))
diff --git a/docs/resources/secret_with_client_credentials.md b/docs/resources/secret_with_client_credentials.md
index 8d2c2e5895..d827292373 100644
--- a/docs/resources/secret_with_client_credentials.md
+++ b/docs/resources/secret_with_client_credentials.md
@@ -56,6 +56,7 @@ resource "snowflake_secret_with_client_credentials" "test" {
- `describe_output` (List of Object) Outputs the result of `DESCRIBE SECRET` for the given secret. (see [below for nested schema](#nestedatt--describe_output))
- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
+- `secret_type` (String) Specifies a type for the secret. This field is used for checking external changes and recreating the resources if needed.
- `show_output` (List of Object) Outputs the result of `SHOW SECRETS` for the given secret. (see [below for nested schema](#nestedatt--show_output))
diff --git a/docs/resources/secret_with_generic_string.md b/docs/resources/secret_with_generic_string.md
index 2a2783a71e..3b1579c6ce 100644
--- a/docs/resources/secret_with_generic_string.md
+++ b/docs/resources/secret_with_generic_string.md
@@ -53,6 +53,7 @@ resource "snowflake_secret_with_generic_string" "test" {
- `describe_output` (List of Object) Outputs the result of `DESCRIBE SECRET` for the given secret. (see [below for nested schema](#nestedatt--describe_output))
- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
+- `secret_type` (String) Specifies a type for the secret. This field is used for checking external changes and recreating the resources if needed.
- `show_output` (List of Object) Outputs the result of `SHOW SECRETS` for the given secret. (see [below for nested schema](#nestedatt--show_output))
diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go
index 9103013a55..bd7e5f8413 100644
--- a/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go
+++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go
@@ -73,6 +73,22 @@ var allResourceSchemaDefs = []ResourceSchemaDef{
name: "StreamOnExternalTable",
schema: resources.StreamOnExternalTable().Schema,
},
+ {
+ name: "SecretWithAuthorizationCodeGrant",
+ schema: resources.SecretWithAuthorizationCodeGrant().Schema,
+ },
+ {
+ name: "SecretWithBasicAuthentication",
+ schema: resources.SecretWithBasicAuthentication().Schema,
+ },
+ {
+ name: "SecretWithClientCredentials",
+ schema: resources.SecretWithClientCredentials().Schema,
+ },
+ {
+ name: "SecretWithGenericString",
+ schema: resources.SecretWithGenericString().Schema,
+ },
{
name: "StreamOnDirectoryTable",
schema: resources.StreamOnDirectoryTable().Schema,
diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_ext.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_ext.go
index 0044880efd..e5da2b69e7 100644
--- a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_ext.go
+++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_ext.go
@@ -4,7 +4,7 @@ import (
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert"
)
-func (s *SecretWithAuthorizationCodeResourceAssert) HasOauthRefreshTokenExpiryTimeNotEmpty() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasOauthRefreshTokenExpiryTimeNotEmpty() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValuePresent("oauth_refresh_token_expiry_time"))
return s
}
diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_gen.go
index 610faae14e..45684561ab 100644
--- a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_gen.go
+++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_authorization_code_grant_resource_gen.go
@@ -8,22 +8,22 @@ import (
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert"
)
-type SecretWithAuthorizationCodeResourceAssert struct {
+type SecretWithAuthorizationCodeGrantResourceAssert struct {
*assert.ResourceAssert
}
-func SecretWithAuthorizationCodeResource(t *testing.T, name string) *SecretWithAuthorizationCodeResourceAssert {
+func SecretWithAuthorizationCodeGrantResource(t *testing.T, name string) *SecretWithAuthorizationCodeGrantResourceAssert {
t.Helper()
- return &SecretWithAuthorizationCodeResourceAssert{
+ return &SecretWithAuthorizationCodeGrantResourceAssert{
ResourceAssert: assert.NewResourceAssert(name, "resource"),
}
}
-func ImportedSecretWithAuthorizationCodeResource(t *testing.T, id string) *SecretWithAuthorizationCodeResourceAssert {
+func ImportedSecretWithAuthorizationCodeGrantResource(t *testing.T, id string) *SecretWithAuthorizationCodeGrantResourceAssert {
t.Helper()
- return &SecretWithAuthorizationCodeResourceAssert{
+ return &SecretWithAuthorizationCodeGrantResourceAssert{
ResourceAssert: assert.NewImportedResourceAssert(id, "imported resource"),
}
}
@@ -32,86 +32,96 @@ func ImportedSecretWithAuthorizationCodeResource(t *testing.T, id string) *Secre
// Attribute value string checks //
///////////////////////////////////
-func (s *SecretWithAuthorizationCodeResourceAssert) HasApiAuthenticationString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasApiAuthenticationString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("api_authentication", expected))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasCommentString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasCommentString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("comment", expected))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasDatabaseString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasDatabaseString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("database", expected))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasFullyQualifiedNameString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasFullyQualifiedNameString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("fully_qualified_name", expected))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNameString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNameString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("name", expected))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasOauthRefreshTokenString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasOauthRefreshTokenString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("oauth_refresh_token", expected))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasOauthRefreshTokenExpiryTimeString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasOauthRefreshTokenExpiryTimeString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("oauth_refresh_token_expiry_time", expected))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasSchemaString(expected string) *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasSchemaString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueSet("schema", expected))
return s
}
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasSecretTypeString(expected string) *SecretWithAuthorizationCodeGrantResourceAssert {
+ s.AddAssertion(assert.ValueSet("secret_type", expected))
+ return s
+}
+
////////////////////////////
// Attribute empty checks //
////////////////////////////
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoApiAuthentication() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoApiAuthentication() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("api_authentication"))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoComment() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoComment() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("comment"))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoDatabase() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoDatabase() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("database"))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoFullyQualifiedName() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoFullyQualifiedName() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("fully_qualified_name"))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoName() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoName() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("name"))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoOauthRefreshToken() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoOauthRefreshToken() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("oauth_refresh_token"))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoOauthRefreshTokenExpiryTime() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoOauthRefreshTokenExpiryTime() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("oauth_refresh_token_expiry_time"))
return s
}
-func (s *SecretWithAuthorizationCodeResourceAssert) HasNoSchema() *SecretWithAuthorizationCodeResourceAssert {
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoSchema() *SecretWithAuthorizationCodeGrantResourceAssert {
s.AddAssertion(assert.ValueNotSet("schema"))
return s
}
+
+func (s *SecretWithAuthorizationCodeGrantResourceAssert) HasNoSecretType() *SecretWithAuthorizationCodeGrantResourceAssert {
+ s.AddAssertion(assert.ValueNotSet("secret_type"))
+ return s
+}
diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_basic_authentication_resource_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_basic_authentication_resource_gen.go
index 186aed6035..5c638a4a09 100644
--- a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_basic_authentication_resource_gen.go
+++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_basic_authentication_resource_gen.go
@@ -62,6 +62,11 @@ func (s *SecretWithBasicAuthenticationResourceAssert) HasSchemaString(expected s
return s
}
+func (s *SecretWithBasicAuthenticationResourceAssert) HasSecretTypeString(expected string) *SecretWithBasicAuthenticationResourceAssert {
+ s.AddAssertion(assert.ValueSet("secret_type", expected))
+ return s
+}
+
func (s *SecretWithBasicAuthenticationResourceAssert) HasUsernameString(expected string) *SecretWithBasicAuthenticationResourceAssert {
s.AddAssertion(assert.ValueSet("username", expected))
return s
@@ -101,6 +106,11 @@ func (s *SecretWithBasicAuthenticationResourceAssert) HasNoSchema() *SecretWithB
return s
}
+func (s *SecretWithBasicAuthenticationResourceAssert) HasNoSecretType() *SecretWithBasicAuthenticationResourceAssert {
+ s.AddAssertion(assert.ValueNotSet("secret_type"))
+ return s
+}
+
func (s *SecretWithBasicAuthenticationResourceAssert) HasNoUsername() *SecretWithBasicAuthenticationResourceAssert {
s.AddAssertion(assert.ValueNotSet("username"))
return s
diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_client_credentials_resource_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_client_credentials_resource_gen.go
index 12a36fa46d..68aaded5df 100644
--- a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_client_credentials_resource_gen.go
+++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_client_credentials_resource_gen.go
@@ -67,6 +67,11 @@ func (s *SecretWithClientCredentialsResourceAssert) HasSchemaString(expected str
return s
}
+func (s *SecretWithClientCredentialsResourceAssert) HasSecretTypeString(expected string) *SecretWithClientCredentialsResourceAssert {
+ s.AddAssertion(assert.ValueSet("secret_type", expected))
+ return s
+}
+
////////////////////////////
// Attribute empty checks //
////////////////////////////
@@ -105,3 +110,8 @@ func (s *SecretWithClientCredentialsResourceAssert) HasNoSchema() *SecretWithCli
s.AddAssertion(assert.ValueNotSet("schema"))
return s
}
+
+func (s *SecretWithClientCredentialsResourceAssert) HasNoSecretType() *SecretWithClientCredentialsResourceAssert {
+ s.AddAssertion(assert.ValueNotSet("secret_type"))
+ return s
+}
diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_generic_string_resource_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_generic_string_resource_gen.go
index d2d682aa1f..259dd6dab0 100644
--- a/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_generic_string_resource_gen.go
+++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/secret_with_generic_string_resource_gen.go
@@ -62,6 +62,11 @@ func (s *SecretWithGenericStringResourceAssert) HasSecretStringString(expected s
return s
}
+func (s *SecretWithGenericStringResourceAssert) HasSecretTypeString(expected string) *SecretWithGenericStringResourceAssert {
+ s.AddAssertion(assert.ValueSet("secret_type", expected))
+ return s
+}
+
////////////////////////////
// Attribute empty checks //
////////////////////////////
@@ -95,3 +100,8 @@ func (s *SecretWithGenericStringResourceAssert) HasNoSecretString() *SecretWithG
s.AddAssertion(assert.ValueNotSet("secret_string"))
return s
}
+
+func (s *SecretWithGenericStringResourceAssert) HasNoSecretType() *SecretWithGenericStringResourceAssert {
+ s.AddAssertion(assert.ValueNotSet("secret_type"))
+ return s
+}
diff --git a/pkg/acceptance/bettertestspoc/config/model/secret_with_oauth_authorization_code_grant_model_gen.go b/pkg/acceptance/bettertestspoc/config/model/secret_with_authorization_code_grant_model_gen.go
similarity index 92%
rename from pkg/acceptance/bettertestspoc/config/model/secret_with_oauth_authorization_code_grant_model_gen.go
rename to pkg/acceptance/bettertestspoc/config/model/secret_with_authorization_code_grant_model_gen.go
index 212740cc5d..144a4fc212 100644
--- a/pkg/acceptance/bettertestspoc/config/model/secret_with_oauth_authorization_code_grant_model_gen.go
+++ b/pkg/acceptance/bettertestspoc/config/model/secret_with_authorization_code_grant_model_gen.go
@@ -18,6 +18,7 @@ type SecretWithAuthorizationCodeGrantModel struct {
OauthRefreshToken tfconfig.Variable `json:"oauth_refresh_token,omitempty"`
OauthRefreshTokenExpiryTime tfconfig.Variable `json:"oauth_refresh_token_expiry_time,omitempty"`
Schema tfconfig.Variable `json:"schema,omitempty"`
+ SecretType tfconfig.Variable `json:"secret_type,omitempty"`
*config.ResourceModelMeta
}
@@ -49,9 +50,9 @@ func SecretWithAuthorizationCodeGrantWithDefaultMeta(
apiAuthentication string,
database string,
name string,
+ schema string,
oauthRefreshToken string,
oauthRefreshTokenExpiryTime string,
- schema string,
) *SecretWithAuthorizationCodeGrantModel {
s := &SecretWithAuthorizationCodeGrantModel{ResourceModelMeta: config.DefaultMeta(resources.SecretWithAuthorizationCodeGrant)}
s.WithApiAuthentication(apiAuthentication)
@@ -107,6 +108,11 @@ func (s *SecretWithAuthorizationCodeGrantModel) WithSchema(schema string) *Secre
return s
}
+func (s *SecretWithAuthorizationCodeGrantModel) WithSecretType(secretType string) *SecretWithAuthorizationCodeGrantModel {
+ s.SecretType = tfconfig.StringVariable(secretType)
+ return s
+}
+
//////////////////////////////////////////
// below it's possible to set any value //
//////////////////////////////////////////
@@ -150,3 +156,8 @@ func (s *SecretWithAuthorizationCodeGrantModel) WithSchemaValue(value tfconfig.V
s.Schema = value
return s
}
+
+func (s *SecretWithAuthorizationCodeGrantModel) WithSecretTypeValue(value tfconfig.Variable) *SecretWithAuthorizationCodeGrantModel {
+ s.SecretType = value
+ return s
+}
diff --git a/pkg/acceptance/bettertestspoc/config/model/secret_with_basic_authentication_model_gen.go b/pkg/acceptance/bettertestspoc/config/model/secret_with_basic_authentication_model_gen.go
index 975b3c7ff7..b3c0f4ee83 100644
--- a/pkg/acceptance/bettertestspoc/config/model/secret_with_basic_authentication_model_gen.go
+++ b/pkg/acceptance/bettertestspoc/config/model/secret_with_basic_authentication_model_gen.go
@@ -16,6 +16,7 @@ type SecretWithBasicAuthenticationModel struct {
Name tfconfig.Variable `json:"name,omitempty"`
Password tfconfig.Variable `json:"password,omitempty"`
Schema tfconfig.Variable `json:"schema,omitempty"`
+ SecretType tfconfig.Variable `json:"secret_type,omitempty"`
Username tfconfig.Variable `json:"username,omitempty"`
*config.ResourceModelMeta
@@ -92,6 +93,11 @@ func (s *SecretWithBasicAuthenticationModel) WithSchema(schema string) *SecretWi
return s
}
+func (s *SecretWithBasicAuthenticationModel) WithSecretType(secretType string) *SecretWithBasicAuthenticationModel {
+ s.SecretType = tfconfig.StringVariable(secretType)
+ return s
+}
+
func (s *SecretWithBasicAuthenticationModel) WithUsername(username string) *SecretWithBasicAuthenticationModel {
s.Username = tfconfig.StringVariable(username)
return s
@@ -131,6 +137,11 @@ func (s *SecretWithBasicAuthenticationModel) WithSchemaValue(value tfconfig.Vari
return s
}
+func (s *SecretWithBasicAuthenticationModel) WithSecretTypeValue(value tfconfig.Variable) *SecretWithBasicAuthenticationModel {
+ s.SecretType = value
+ return s
+}
+
func (s *SecretWithBasicAuthenticationModel) WithUsernameValue(value tfconfig.Variable) *SecretWithBasicAuthenticationModel {
s.Username = value
return s
diff --git a/pkg/acceptance/bettertestspoc/config/model/secret_with_client_credentials_model_ext.go b/pkg/acceptance/bettertestspoc/config/model/secret_with_client_credentials_model_ext.go
new file mode 100644
index 0000000000..6555f0f1cf
--- /dev/null
+++ b/pkg/acceptance/bettertestspoc/config/model/secret_with_client_credentials_model_ext.go
@@ -0,0 +1,13 @@
+package model
+
+import tfconfig "github.com/hashicorp/terraform-plugin-testing/config"
+
+func (s *SecretWithClientCredentialsModel) WithOauthScopes(oauthScopes []string) *SecretWithClientCredentialsModel {
+ oauthScopesStringVariables := make([]tfconfig.Variable, len(oauthScopes))
+ for i, v := range oauthScopes {
+ oauthScopesStringVariables[i] = tfconfig.StringVariable(v)
+ }
+
+ s.OauthScopes = tfconfig.SetVariable(oauthScopesStringVariables...)
+ return s
+}
diff --git a/pkg/acceptance/bettertestspoc/config/model/secret_with_oauth_client_credentials_model_gen.go b/pkg/acceptance/bettertestspoc/config/model/secret_with_client_credentials_model_gen.go
similarity index 91%
rename from pkg/acceptance/bettertestspoc/config/model/secret_with_oauth_client_credentials_model_gen.go
rename to pkg/acceptance/bettertestspoc/config/model/secret_with_client_credentials_model_gen.go
index 9e093b48d0..bd69bffbb2 100644
--- a/pkg/acceptance/bettertestspoc/config/model/secret_with_oauth_client_credentials_model_gen.go
+++ b/pkg/acceptance/bettertestspoc/config/model/secret_with_client_credentials_model_gen.go
@@ -17,6 +17,7 @@ type SecretWithClientCredentialsModel struct {
Name tfconfig.Variable `json:"name,omitempty"`
OauthScopes tfconfig.Variable `json:"oauth_scopes,omitempty"`
Schema tfconfig.Variable `json:"schema,omitempty"`
+ SecretType tfconfig.Variable `json:"secret_type,omitempty"`
*config.ResourceModelMeta
}
@@ -94,6 +95,11 @@ func (s *SecretWithClientCredentialsModel) WithSchema(schema string) *SecretWith
return s
}
+func (s *SecretWithClientCredentialsModel) WithSecretType(secretType string) *SecretWithClientCredentialsModel {
+ s.SecretType = tfconfig.StringVariable(secretType)
+ return s
+}
+
//////////////////////////////////////////
// below it's possible to set any value //
//////////////////////////////////////////
@@ -132,12 +138,8 @@ func (s *SecretWithClientCredentialsModel) WithSchemaValue(value tfconfig.Variab
s.Schema = value
return s
}
-func (s *SecretWithClientCredentialsModel) WithOauthScopes(oauthScopes []string) *SecretWithClientCredentialsModel {
- oauthScopesStringVariables := make([]tfconfig.Variable, len(oauthScopes))
- for i, v := range oauthScopes {
- oauthScopesStringVariables[i] = tfconfig.StringVariable(v)
- }
- s.OauthScopes = tfconfig.SetVariable(oauthScopesStringVariables...)
+func (s *SecretWithClientCredentialsModel) WithSecretTypeValue(value tfconfig.Variable) *SecretWithClientCredentialsModel {
+ s.SecretType = value
return s
}
diff --git a/pkg/acceptance/bettertestspoc/config/model/secret_with_generic_string_model_gen.go b/pkg/acceptance/bettertestspoc/config/model/secret_with_generic_string_model_gen.go
index e2f441ef3f..c1cbe7d05e 100644
--- a/pkg/acceptance/bettertestspoc/config/model/secret_with_generic_string_model_gen.go
+++ b/pkg/acceptance/bettertestspoc/config/model/secret_with_generic_string_model_gen.go
@@ -16,6 +16,7 @@ type SecretWithGenericStringModel struct {
Name tfconfig.Variable `json:"name,omitempty"`
Schema tfconfig.Variable `json:"schema,omitempty"`
SecretString tfconfig.Variable `json:"secret_string,omitempty"`
+ SecretType tfconfig.Variable `json:"secret_type,omitempty"`
*config.ResourceModelMeta
}
@@ -87,6 +88,11 @@ func (s *SecretWithGenericStringModel) WithSecretString(secretString string) *Se
return s
}
+func (s *SecretWithGenericStringModel) WithSecretType(secretType string) *SecretWithGenericStringModel {
+ s.SecretType = tfconfig.StringVariable(secretType)
+ return s
+}
+
//////////////////////////////////////////
// below it's possible to set any value //
//////////////////////////////////////////
@@ -120,3 +126,8 @@ func (s *SecretWithGenericStringModel) WithSecretStringValue(value tfconfig.Vari
s.SecretString = value
return s
}
+
+func (s *SecretWithGenericStringModel) WithSecretTypeValue(value tfconfig.Variable) *SecretWithGenericStringModel {
+ s.SecretType = value
+ return s
+}
diff --git a/pkg/datasources/secrets_acceptance_test.go b/pkg/datasources/secrets_acceptance_test.go
index 28627337b2..41d454a29a 100644
--- a/pkg/datasources/secrets_acceptance_test.go
+++ b/pkg/datasources/secrets_acceptance_test.go
@@ -62,7 +62,7 @@ func TestAcc_Secrets_WithClientCredentials(t *testing.T) {
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()).
HasComment("").
- HasSecretType(sdk.SecretTypeOAuth2),
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.show_output.0.oauth_scopes.#", "2")),
assert.Check(resource.TestCheckTypeSetElemAttr(dsName, "secrets.0.show_output.0.oauth_scopes.*", "username")),
assert.Check(resource.TestCheckTypeSetElemAttr(dsName, "secrets.0.show_output.0.oauth_scopes.*", "test_scope")),
@@ -70,7 +70,7 @@ func TestAcc_Secrets_WithClientCredentials(t *testing.T) {
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.name", id.Name())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.database_name", id.DatabaseName())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.schema_name", id.SchemaName())),
- assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", sdk.SecretTypeOAuth2)),
+ assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", string(sdk.SecretTypeOAuth2))),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.username", "")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.comment", "")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.oauth_scopes.#", "2")),
@@ -117,13 +117,13 @@ func TestAcc_Secrets_WithAuthorizationCodeGrant(t *testing.T) {
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()).
HasComment("test_comment").
- HasSecretType(sdk.SecretTypeOAuth2),
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.show_output.0.oauth_scopes.#", "0")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.name", id.Name())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.database_name", id.DatabaseName())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.schema_name", id.SchemaName())),
- assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", sdk.SecretTypeOAuth2)),
+ assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", string(sdk.SecretTypeOAuth2))),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.username", "")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.comment", "test_comment")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.oauth_scopes.#", "0")),
@@ -158,13 +158,13 @@ func TestAcc_Secrets_WithBasicAuthentication(t *testing.T) {
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()).
HasComment("").
- HasSecretType(sdk.SecretTypePassword),
+ HasSecretType(string(sdk.SecretTypePassword)),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.show_output.0.oauth_scopes.#", "0")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.name", id.Name())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.database_name", id.DatabaseName())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.schema_name", id.SchemaName())),
- assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", sdk.SecretTypePassword)),
+ assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", string(sdk.SecretTypePassword))),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.username", "test_username")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.comment", "")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.oauth_scopes.#", "0")),
@@ -199,14 +199,14 @@ func TestAcc_Secrets_WithGenericString(t *testing.T) {
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()).
HasComment("").
- HasSecretType(sdk.SecretTypeGenericString),
+ HasSecretType(string(sdk.SecretTypeGenericString)),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.show_output.0.oauth_scopes.#", "0")),
assert.Check(resource.TestCheckResourceAttrSet(dsName, "secrets.0.describe_output.0.created_on")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.name", id.Name())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.database_name", id.DatabaseName())),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.schema_name", id.SchemaName())),
- assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", sdk.SecretTypeGenericString)),
+ assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.secret_type", string(sdk.SecretTypeGenericString))),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.username", "")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.comment", "")),
assert.Check(resource.TestCheckResourceAttr(dsName, "secrets.0.describe_output.0.oauth_scopes.#", "0")),
diff --git a/pkg/resources/custom_diffs.go b/pkg/resources/custom_diffs.go
index 4d41624539..f884fc7e9b 100644
--- a/pkg/resources/custom_diffs.go
+++ b/pkg/resources/custom_diffs.go
@@ -196,6 +196,38 @@ func RecreateWhenUserTypeChangedExternally(userType sdk.UserType) schema.Customi
}
}
+func RecreateWhenSecretTypeChangedExternally(secretType sdk.SecretType) schema.CustomizeDiffFunc {
+ return func(_ context.Context, diff *schema.ResourceDiff, _ interface{}) error {
+ if n := diff.Get("secret_type"); n != nil {
+ logging.DebugLogger.Printf("[DEBUG] new external value for secret type %s\n", n.(string))
+
+ diffSecretType, _ := sdk.ToSecretType(n.(string))
+ if acceptableSecretTypes, ok := sdk.AcceptableSecretTypes[secretType]; ok && !slices.Contains(acceptableSecretTypes, diffSecretType) {
+ return errors.Join(diff.SetNew("secret_type", ""), diff.ForceNew("secret_type"))
+ }
+ // both client_credentials and authorization_code_grant secrets have the same type: "OAUTH2"
+ // to detect the external type change we need to check fields that are required in one, but should be absent in the other
+ // we will check if the 'oauth_refresh_token_expiry_time' is present in the describe_output
+ // since it is required in authorization_code_grant flow and should be empty in client_credentials flow
+ if diffSecretType == sdk.SecretTypeOAuth2 {
+ var isRefreshTokenExpiryTimeEmpty bool
+ rt := diff.Get("describe_output.0.oauth_refresh_token_expiry_time").(string)
+
+ switch secretType {
+ case sdk.SecretTypeOAuth2AuthorizationCodeGrant:
+ isRefreshTokenExpiryTimeEmpty = rt == ""
+ case sdk.SecretTypeOAuth2ClientCredentials:
+ isRefreshTokenExpiryTimeEmpty = rt != ""
+ }
+ if isRefreshTokenExpiryTimeEmpty {
+ return errors.Join(diff.SetNew("secret_type", ""), diff.ForceNew("secret_type"))
+ }
+ }
+ }
+ return nil
+ }
+}
+
// RecreateWhenStreamIsStale detects when the stream is stale, and sets a `false` value for `stale` field.
// This means that the provider can detect that change in `stale` from `true` to `false`, where `false` is our desired state.
func RecreateWhenStreamIsStale() schema.CustomizeDiffFunc {
diff --git a/pkg/resources/custom_diffs_test.go b/pkg/resources/custom_diffs_test.go
index b1e3772d6b..8942eca24c 100644
--- a/pkg/resources/custom_diffs_test.go
+++ b/pkg/resources/custom_diffs_test.go
@@ -143,6 +143,18 @@ func createProviderWithNamedPropertyAndCustomDiff(t *testing.T, propertyName str
}
}
+func createProviderWithCustomSchemaAndCustomDiff(t *testing.T, customSchema map[string]*schema.Schema, customDiffFunc schema.CustomizeDiffFunc) *schema.Provider {
+ t.Helper()
+ return &schema.Provider{
+ ResourcesMap: map[string]*schema.Resource{
+ "test": {
+ Schema: customSchema,
+ CustomizeDiff: customDiffFunc,
+ },
+ },
+ }
+}
+
func calculateDiff(t *testing.T, providerConfig *schema.Provider, rawConfigValue cty.Value, stateValue map[string]any) *terraform.InstanceDiff {
t.Helper()
diff, err := providerConfig.ResourcesMap["test"].Diff(
@@ -786,3 +798,287 @@ func Test_RecreateWhenUserTypeChangedExternally(t *testing.T) {
})
}
}
+
+func Test_RecreateWhenSecretTypeChangedExternally(t *testing.T) {
+ tests := []struct {
+ name string
+ secretType sdk.SecretType
+ stateValue map[string]string
+ wantForceNew bool
+ }{
+ // password type
+ {
+ name: "password - nothing in state",
+ secretType: sdk.SecretTypePassword,
+ stateValue: map[string]string{},
+ wantForceNew: true,
+ },
+ {
+ name: "password - empty value in state",
+ secretType: sdk.SecretTypePassword,
+ stateValue: map[string]string{
+ "secret_type": "",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "password - password in state",
+ secretType: sdk.SecretTypePassword,
+ stateValue: map[string]string{
+ "secret_type": "PASSWORD",
+ },
+ wantForceNew: false,
+ },
+ {
+ name: "password - password in state lowercased",
+ secretType: sdk.SecretTypePassword,
+ stateValue: map[string]string{
+ "secret_type": "password",
+ },
+ wantForceNew: false,
+ },
+ {
+ name: "password - oauth2 in state",
+ secretType: sdk.SecretTypePassword,
+ stateValue: map[string]string{
+ "secret_type": "OAUTH2",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "password - generic_string in state",
+ secretType: sdk.SecretTypePassword,
+ stateValue: map[string]string{
+ "secret_type": "GENERIC_STRING",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "password - oauth2 in state lowercased",
+ secretType: sdk.SecretTypePassword,
+ stateValue: map[string]string{
+ "secret_type": "oauth2",
+ },
+ wantForceNew: true,
+ },
+ // generic string type
+ {
+ name: "generic_string - nothing in state",
+ secretType: sdk.SecretTypeGenericString,
+ stateValue: map[string]string{},
+ wantForceNew: true,
+ },
+ {
+ name: "generic_string - empty value in state",
+ secretType: sdk.SecretTypeGenericString,
+ stateValue: map[string]string{
+ "secret_type": "",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "generic_string - generic_string in state",
+ secretType: sdk.SecretTypeGenericString,
+ stateValue: map[string]string{
+ "secret_type": "generic_string",
+ },
+ wantForceNew: false,
+ },
+ {
+ name: "generic_string - generic_string in state lowercased",
+ secretType: sdk.SecretTypeGenericString,
+ stateValue: map[string]string{
+ "secret_type": "generic_string",
+ },
+ wantForceNew: false,
+ },
+ {
+ name: "generic_string - oauth2 in state",
+ secretType: sdk.SecretTypeGenericString,
+ stateValue: map[string]string{
+ "secret_type": "OAUTH2",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "generic_string - password in state",
+ secretType: sdk.SecretTypeGenericString,
+ stateValue: map[string]string{
+ "secret_type": "PASSWORD",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "generic_string - oauth2 in state lowercased",
+ secretType: sdk.SecretTypeGenericString,
+ stateValue: map[string]string{
+ "secret_type": "oauth2",
+ },
+ wantForceNew: true,
+ },
+ // oauth2 authorization code grant type
+ {
+ name: "oauth2 authorization code grant - nothing in state",
+ secretType: sdk.SecretTypeOAuth2AuthorizationCodeGrant,
+ stateValue: map[string]string{},
+ wantForceNew: true,
+ },
+ {
+ name: "oauth2 authorization code grant - empty value in state",
+ secretType: sdk.SecretTypeOAuth2AuthorizationCodeGrant,
+ stateValue: map[string]string{
+ "secret_type": "",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "oauth2 authorization code grant - password in state",
+ secretType: sdk.SecretTypeOAuth2AuthorizationCodeGrant,
+ stateValue: map[string]string{
+ "secret_type": "PASSWORD",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "oauth2 authorization code grant - generic_string in state",
+ secretType: sdk.SecretTypeOAuth2AuthorizationCodeGrant,
+ stateValue: map[string]string{
+ "secret_type": "GENERIC_STRING",
+ },
+ wantForceNew: true,
+ },
+ // oauth2 client credentials type
+ {
+ name: "oauth2 client credentials - nothing in state",
+ secretType: sdk.SecretTypeOAuth2ClientCredentials,
+ stateValue: map[string]string{},
+ wantForceNew: true,
+ },
+ {
+ name: "oauth2 client credentials - empty value in state",
+ secretType: sdk.SecretTypeOAuth2ClientCredentials,
+ stateValue: map[string]string{
+ "secret_type": "",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "oauth2 client credentials - password in state",
+ secretType: sdk.SecretTypeOAuth2ClientCredentials,
+ stateValue: map[string]string{
+ "secret_type": "PASSWORD",
+ },
+ wantForceNew: true,
+ },
+ {
+ name: "oauth2 client credentials - generic_string in state",
+ secretType: sdk.SecretTypeOAuth2ClientCredentials,
+ stateValue: map[string]string{
+ "secret_type": "GENERIC_STRING",
+ },
+ wantForceNew: true,
+ },
+ }
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ customDiff := resources.RecreateWhenSecretTypeChangedExternally(tt.secretType)
+ testProvider := createProviderWithNamedPropertyAndCustomDiff(t, "secret_type", &schema.Schema{
+ Type: schema.TypeString,
+ Computed: true,
+ }, customDiff)
+ diff := calculateDiffFromAttributes(
+ t,
+ testProvider,
+ tt.stateValue,
+ map[string]any{},
+ )
+ assert.Equal(t, tt.wantForceNew, diff.RequiresNew())
+ })
+ }
+}
+
+func Test_RecreateWhenSecretTypeChangedExternallyForOAuth2(t *testing.T) {
+ tests := []struct {
+ name string
+ secretType sdk.SecretType
+ stateValue map[string]string
+ wantForceNew bool
+ }{
+ // config - authorization code
+ // external change - drop and recreate with the same id but as oauth2 with client credentials
+ {
+ name: "oauth2 authorization code - oauth2 client credentials in state",
+ secretType: sdk.SecretTypeOAuth2AuthorizationCodeGrant,
+ stateValue: map[string]string{
+ "secret_type": "OAUTH2",
+ "describe_output.0.oauth_refresh_token_expiry_time": "",
+ },
+ wantForceNew: true,
+ },
+ // config - client credentials
+ // external change - drop and recreate with the same id but as oauth2 with authorization code grant
+ {
+ name: "oauth2 client credentials - oauth2 authorization code in state",
+ secretType: sdk.SecretTypeOAuth2ClientCredentials,
+ stateValue: map[string]string{
+ "secret_type": "OAUTH2",
+ "describe_output.0.oauth_refresh_token_expiry_time": "some test date here",
+ },
+ wantForceNew: true,
+ },
+ // no external change
+ {
+ name: "oauth2 authorization code - oauth2 authorization code in state",
+ secretType: sdk.SecretTypeOAuth2AuthorizationCodeGrant,
+ stateValue: map[string]string{
+ "secret_type": "OAUTH2",
+ "describe_output.0.oauth_refresh_token_expiry_time": "some test date here",
+ },
+ wantForceNew: false,
+ },
+ // no external change
+ {
+ name: "oauth2 client credentials - oauth2 client credentials code in state",
+ secretType: sdk.SecretTypeOAuth2ClientCredentials,
+ stateValue: map[string]string{
+ "secret_type": "OAUTH2",
+ "describe_output.0.oauth_refresh_token_expiry_time": "",
+ },
+ wantForceNew: false,
+ },
+ }
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ customDiff := resources.RecreateWhenSecretTypeChangedExternally(tt.secretType)
+ testProvider := createProviderWithCustomSchemaAndCustomDiff(t,
+ map[string]*schema.Schema{
+ "secret_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "describe_output": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "oauth_refresh_token_expiry_time": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ },
+ },
+ },
+ customDiff)
+ diff := calculateDiffFromAttributes(
+ t,
+ testProvider,
+ tt.stateValue,
+ map[string]any{},
+ )
+ assert.Equal(t, tt.wantForceNew, diff.RequiresNew())
+ })
+ }
+}
diff --git a/pkg/resources/masking_policy.go b/pkg/resources/masking_policy.go
index 36739fde0f..965945e708 100644
--- a/pkg/resources/masking_policy.go
+++ b/pkg/resources/masking_policy.go
@@ -282,7 +282,7 @@ func ReadMaskingPolicy(withExternalChangesMarking bool) schema.ReadContextFunc {
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"exempt_other_policies", "exempt_other_policies", maskingPolicy.ExemptOtherPolicies, booleanStringFromBool(maskingPolicy.ExemptOtherPolicies), nil},
+ outputMapping{"exempt_other_policies", "exempt_other_policies", maskingPolicy.ExemptOtherPolicies, booleanStringFromBool(maskingPolicy.ExemptOtherPolicies), nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/resources/oauth_integration_for_custom_clients.go b/pkg/resources/oauth_integration_for_custom_clients.go
index 4462651bf2..9669a37b53 100644
--- a/pkg/resources/oauth_integration_for_custom_clients.go
+++ b/pkg/resources/oauth_integration_for_custom_clients.go
@@ -456,7 +456,7 @@ func ReadContextOauthIntegrationForCustomClients(withExternalChangesMarking bool
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"enabled", "enabled", integration.Enabled, booleanStringFromBool(integration.Enabled), nil},
+ outputMapping{"enabled", "enabled", integration.Enabled, booleanStringFromBool(integration.Enabled), nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/resources/oauth_integration_for_partner_applications.go b/pkg/resources/oauth_integration_for_partner_applications.go
index d92d9d4dee..12c18c62ae 100644
--- a/pkg/resources/oauth_integration_for_partner_applications.go
+++ b/pkg/resources/oauth_integration_for_partner_applications.go
@@ -336,7 +336,7 @@ func ReadContextOauthIntegrationForPartnerApplications(withExternalChangesMarkin
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"enabled", "enabled", integration.Enabled, booleanStringFromBool(integration.Enabled), nil},
+ outputMapping{"enabled", "enabled", integration.Enabled, booleanStringFromBool(integration.Enabled), nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/resources/resource_monitor.go b/pkg/resources/resource_monitor.go
index f2b8d63db0..ae8da17fc2 100644
--- a/pkg/resources/resource_monitor.go
+++ b/pkg/resources/resource_monitor.go
@@ -267,13 +267,13 @@ func ReadResourceMonitor(withExternalChangesMarking bool) schema.ReadContextFunc
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"credit_quota", "credit_quota", resourceMonitor.CreditQuota, resourceMonitor.CreditQuota, nil},
- showMapping{"frequency", "frequency", string(resourceMonitor.Frequency), resourceMonitor.Frequency, nil},
- showMapping{"start_time", "start_timestamp", resourceMonitor.StartTime, resourceMonitor.StartTime, nil},
- showMapping{"end_time", "end_timestamp", resourceMonitor.EndTime, resourceMonitor.EndTime, nil},
- showMapping{"notify_at", "notify_triggers", resourceMonitor.NotifyAt, resourceMonitor.NotifyAt, nil},
- showMapping{"suspend_at", "suspend_trigger", resourceMonitor.SuspendAt, resourceMonitor.SuspendAt, nil},
- showMapping{"suspend_immediately_at", "suspend_immediate_trigger", resourceMonitor.SuspendImmediateAt, resourceMonitor.SuspendImmediateAt, nil},
+ outputMapping{"credit_quota", "credit_quota", resourceMonitor.CreditQuota, resourceMonitor.CreditQuota, nil},
+ outputMapping{"frequency", "frequency", string(resourceMonitor.Frequency), resourceMonitor.Frequency, nil},
+ outputMapping{"start_time", "start_timestamp", resourceMonitor.StartTime, resourceMonitor.StartTime, nil},
+ outputMapping{"end_time", "end_timestamp", resourceMonitor.EndTime, resourceMonitor.EndTime, nil},
+ outputMapping{"notify_at", "notify_triggers", resourceMonitor.NotifyAt, resourceMonitor.NotifyAt, nil},
+ outputMapping{"suspend_at", "suspend_trigger", resourceMonitor.SuspendAt, resourceMonitor.SuspendAt, nil},
+ outputMapping{"suspend_immediately_at", "suspend_immediate_trigger", resourceMonitor.SuspendImmediateAt, resourceMonitor.SuspendImmediateAt, nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/resources/saml2_integration.go b/pkg/resources/saml2_integration.go
index 6712fd23fe..a921b96b7e 100644
--- a/pkg/resources/saml2_integration.go
+++ b/pkg/resources/saml2_integration.go
@@ -554,7 +554,7 @@ func ReadContextSAML2Integration(withExternalChangesMarking bool) schema.ReadCon
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"enabled", "enabled", integration.Enabled, booleanStringFromBool(integration.Enabled), nil},
+ outputMapping{"enabled", "enabled", integration.Enabled, booleanStringFromBool(integration.Enabled), nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/resources/schema.go b/pkg/resources/schema.go
index de3c4e2e48..ff9d85efdb 100644
--- a/pkg/resources/schema.go
+++ b/pkg/resources/schema.go
@@ -270,10 +270,10 @@ func ReadContextSchema(withExternalChangesMarking bool) schema.ReadContextFunc {
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"options", "is_transient", schema.IsTransient(), booleanStringFromBool(schema.IsTransient()), func(x any) any {
+ outputMapping{"options", "is_transient", schema.IsTransient(), booleanStringFromBool(schema.IsTransient()), func(x any) any {
return slices.Contains(sdk.ParseCommaSeparatedStringArray(x.(string), false), "TRANSIENT")
}},
- showMapping{"options", "with_managed_access", schema.IsManagedAccess(), booleanStringFromBool(schema.IsManagedAccess()), func(x any) any {
+ outputMapping{"options", "with_managed_access", schema.IsManagedAccess(), booleanStringFromBool(schema.IsManagedAccess()), func(x any) any {
return slices.Contains(sdk.ParseCommaSeparatedStringArray(x.(string), false), "MANAGED ACCESS")
}},
); err != nil {
diff --git a/pkg/resources/secret_common.go b/pkg/resources/secret_common.go
index 95ceebc949..5739ceebcb 100644
--- a/pkg/resources/secret_common.go
+++ b/pkg/resources/secret_common.go
@@ -33,6 +33,11 @@ var secretCommonSchema = map[string]*schema.Schema{
ForceNew: true,
DiffSuppressFunc: suppressIdentifierQuoting,
},
+ "secret_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Specifies a type for the secret. This field is used for checking external changes and recreating the resources if needed.",
+ },
"comment": {
Type: schema.TypeString,
Optional: true,
@@ -64,8 +69,13 @@ func handleSecretImport(d *schema.ResourceData) error {
return nil
}
-func handleSecretRead(d *schema.ResourceData, id sdk.SchemaObjectIdentifier, secret *sdk.Secret, secretDescription *sdk.SecretDetails) error {
+func handleSecretRead(d *schema.ResourceData,
+ id sdk.SchemaObjectIdentifier,
+ secret *sdk.Secret,
+ secretDescription *sdk.SecretDetails,
+) error {
return errors.Join(
+ d.Set("secret_type", secret.SecretType),
d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()),
d.Set("comment", secret.Comment),
d.Set(ShowOutputAttributeName, []map[string]any{schemas.SecretToSchema(secret)}),
diff --git a/pkg/resources/secret_with_basic_authentication.go b/pkg/resources/secret_with_basic_authentication.go
index e4ec6f42fe..595fc6831d 100644
--- a/pkg/resources/secret_with_basic_authentication.go
+++ b/pkg/resources/secret_with_basic_authentication.go
@@ -42,9 +42,9 @@ func SecretWithBasicAuthentication() *schema.Resource {
Description: "Resource used to manage secret objects with Basic Authentication. For more information, check [secret documentation](https://docs.snowflake.com/en/sql-reference/sql/create-secret).",
CustomizeDiff: customdiff.All(
- ComputedIfAnyAttributeChanged(secretBasicAuthenticationSchema, ShowOutputAttributeName, "name", "comment"),
- ComputedIfAnyAttributeChanged(secretBasicAuthenticationSchema, DescribeOutputAttributeName, "name", "username"),
- ComputedIfAnyAttributeChanged(secretBasicAuthenticationSchema, FullyQualifiedNameAttributeName, "name"),
+ ComputedIfAnyAttributeChanged(secretBasicAuthenticationSchema, ShowOutputAttributeName, "comment"),
+ ComputedIfAnyAttributeChanged(secretBasicAuthenticationSchema, DescribeOutputAttributeName, "username"),
+ RecreateWhenSecretTypeChangedExternally(sdk.SecretTypePassword),
),
Schema: secretBasicAuthenticationSchema,
@@ -128,6 +128,7 @@ func ReadContextSecretWithBasicAuthentication(ctx context.Context, d *schema.Res
},
}
}
+
secretDescription, err := client.Secrets.Describe(ctx, id)
if err != nil {
return diag.FromErr(err)
@@ -138,6 +139,7 @@ func ReadContextSecretWithBasicAuthentication(ctx context.Context, d *schema.Res
if err = d.Set("username", secretDescription.Username); err != nil {
return diag.FromErr(err)
}
+
return nil
}
diff --git a/pkg/resources/secret_with_basic_authentication_acceptance_test.go b/pkg/resources/secret_with_basic_authentication_acceptance_test.go
index 5c0aa401cb..3e3b09de19 100644
--- a/pkg/resources/secret_with_basic_authentication_acceptance_test.go
+++ b/pkg/resources/secret_with_basic_authentication_acceptance_test.go
@@ -57,7 +57,7 @@ func TestAcc_SecretWithBasicAuthentication_BasicFlow(t *testing.T) {
resourceshowoutputassert.SecretShowOutput(t, secretName).
HasName(name).
HasDatabaseName(id.DatabaseName()).
- HasSecretType(sdk.SecretTypePassword).
+ HasSecretType(string(sdk.SecretTypePassword)).
HasSchemaName(id.SchemaName()).
HasComment(""),
),
@@ -67,7 +67,7 @@ func TestAcc_SecretWithBasicAuthentication_BasicFlow(t *testing.T) {
resource.TestCheckResourceAttr(secretName, "describe_output.0.name", name),
resource.TestCheckResourceAttr(secretName, "describe_output.0.database_name", id.DatabaseName()),
resource.TestCheckResourceAttr(secretName, "describe_output.0.schema_name", id.SchemaName()),
- resource.TestCheckResourceAttr(secretName, "describe_output.0.secret_type", sdk.SecretTypePassword),
+ resource.TestCheckResourceAttr(secretName, "describe_output.0.secret_type", string(sdk.SecretTypePassword)),
resource.TestCheckResourceAttr(secretName, "describe_output.0.username", "foo"),
resource.TestCheckResourceAttr(secretName, "describe_output.0.comment", ""),
resource.TestCheckResourceAttr(secretName, "describe_output.0.oauth_access_token_expiry_time", ""),
@@ -91,7 +91,7 @@ func TestAcc_SecretWithBasicAuthentication_BasicFlow(t *testing.T) {
HasCommentString(comment),
resourceshowoutputassert.SecretShowOutput(t, secretName).
- HasSecretType(sdk.SecretTypePassword).
+ HasSecretType(string(sdk.SecretTypePassword)).
HasComment(comment),
),
@@ -225,3 +225,54 @@ func TestAcc_SecretWithBasicAuthentication_CreateWithEmptyCredentials(t *testing
},
})
}
+
+func TestAcc_SecretWithBasicAuthentication_ExternalSecretTypeChange(t *testing.T) {
+ id := acc.TestClient().Ids.RandomSchemaObjectIdentifier()
+ name := id.Name()
+ secretModel := model.SecretWithBasicAuthentication("s", id.DatabaseName(), name, "test_pswd", id.SchemaName(), "test_usr")
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories,
+ PreCheck: func() { acc.TestAccPreCheck(t) },
+ TerraformVersionChecks: []tfversion.TerraformVersionCheck{
+ tfversion.RequireAbove(tfversion.Version1_5_0),
+ },
+ CheckDestroy: acc.CheckDestroy(t, resources.SecretWithBasicAuthentication),
+ Steps: []resource.TestStep{
+ // create
+ {
+ Config: config.FromModel(t, secretModel),
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithBasicAuthenticationResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypePassword)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypePassword)),
+ ),
+ ),
+ },
+ // create or replace with different secret type
+ {
+ PreConfig: func() {
+ acc.TestClient().Secret.DropFunc(t, id)()
+ _, cleanup := acc.TestClient().Secret.CreateWithGenericString(t, id, "test_secret_string")
+ t.Cleanup(cleanup)
+ },
+ Config: config.FromModel(t, secretModel),
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectResourceAction(secretModel.ResourceReference(), plancheck.ResourceActionDestroyBeforeCreate),
+ },
+ },
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithBasicAuthenticationResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypePassword)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypePassword)),
+ ),
+ ),
+ },
+ },
+ })
+}
diff --git a/pkg/resources/secret_with_generic_string.go b/pkg/resources/secret_with_generic_string.go
index 42c2fc6f92..ca9dfe55d6 100644
--- a/pkg/resources/secret_with_generic_string.go
+++ b/pkg/resources/secret_with_generic_string.go
@@ -36,9 +36,9 @@ func SecretWithGenericString() *schema.Resource {
Description: "Resource used to manage secret objects with Generic String. For more information, check [secret documentation](https://docs.snowflake.com/en/sql-reference/sql/create-secret).",
CustomizeDiff: customdiff.All(
- ComputedIfAnyAttributeChanged(secretGenericStringSchema, DescribeOutputAttributeName, "name"),
- ComputedIfAnyAttributeChanged(secretGenericStringSchema, ShowOutputAttributeName, "name", "comment"),
- ComputedIfAnyAttributeChanged(secretGenericStringSchema, FullyQualifiedNameAttributeName, "name"),
+ ComputedIfAnyAttributeChanged(secretGenericStringSchema, ShowOutputAttributeName, "comment"),
+ ComputedIfAnyAttributeChanged(secretGenericStringSchema, DescribeOutputAttributeName),
+ RecreateWhenSecretTypeChangedExternally(sdk.SecretTypeGenericString),
),
Schema: secretGenericStringSchema,
diff --git a/pkg/resources/secret_with_generic_string_acceptance_test.go b/pkg/resources/secret_with_generic_string_acceptance_test.go
index d2eb8a54cf..8f57a8924d 100644
--- a/pkg/resources/secret_with_generic_string_acceptance_test.go
+++ b/pkg/resources/secret_with_generic_string_acceptance_test.go
@@ -54,7 +54,7 @@ func TestAcc_SecretWithGenericString_BasicFlow(t *testing.T) {
resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
HasName(name).
HasDatabaseName(id.DatabaseName()).
- HasSecretType(sdk.SecretTypeGenericString).
+ HasSecretType(string(sdk.SecretTypeGenericString)).
HasSchemaName(id.SchemaName()).
HasComment(""),
),
@@ -64,7 +64,7 @@ func TestAcc_SecretWithGenericString_BasicFlow(t *testing.T) {
resource.TestCheckResourceAttr(secretName, "describe_output.0.name", name),
resource.TestCheckResourceAttr(secretName, "describe_output.0.database_name", id.DatabaseName()),
resource.TestCheckResourceAttr(secretName, "describe_output.0.schema_name", id.SchemaName()),
- resource.TestCheckResourceAttr(secretName, "describe_output.0.secret_type", sdk.SecretTypeGenericString),
+ resource.TestCheckResourceAttr(secretName, "describe_output.0.secret_type", string(sdk.SecretTypeGenericString)),
resource.TestCheckResourceAttr(secretName, "describe_output.0.username", ""),
resource.TestCheckResourceAttr(secretName, "describe_output.0.comment", ""),
resource.TestCheckResourceAttr(secretName, "describe_output.0.oauth_access_token_expiry_time", ""),
@@ -90,7 +90,7 @@ func TestAcc_SecretWithGenericString_BasicFlow(t *testing.T) {
HasCommentString(comment),
resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
- HasSecretType(sdk.SecretTypeGenericString).
+ HasSecretType(string(sdk.SecretTypeGenericString)).
HasComment(comment),
),
@@ -185,3 +185,54 @@ func TestAcc_SecretWithGenericString_BasicFlow(t *testing.T) {
},
})
}
+
+func TestAcc_SecretWithGenericString_ExternalSecretTypeChange(t *testing.T) {
+ id := acc.TestClient().Ids.RandomSchemaObjectIdentifier()
+ name := id.Name()
+ secretModel := model.SecretWithGenericString("s", id.DatabaseName(), name, id.SchemaName(), "test_usr")
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories,
+ PreCheck: func() { acc.TestAccPreCheck(t) },
+ TerraformVersionChecks: []tfversion.TerraformVersionCheck{
+ tfversion.RequireAbove(tfversion.Version1_5_0),
+ },
+ CheckDestroy: acc.CheckDestroy(t, resources.SecretWithGenericString),
+ Steps: []resource.TestStep{
+ // create
+ {
+ Config: config.FromModel(t, secretModel),
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithGenericStringResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeGenericString)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeGenericString)),
+ ),
+ ),
+ },
+ // create or replace with different secret type
+ {
+ PreConfig: func() {
+ acc.TestClient().Secret.DropFunc(t, id)()
+ _, cleanup := acc.TestClient().Secret.CreateWithBasicAuthenticationFlow(t, id, "test_pswd", "test_usr")
+ t.Cleanup(cleanup)
+ },
+ Config: config.FromModel(t, secretModel),
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectResourceAction(secretModel.ResourceReference(), plancheck.ResourceActionDestroyBeforeCreate),
+ },
+ },
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithGenericStringResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeGenericString)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeGenericString)),
+ ),
+ ),
+ },
+ },
+ })
+}
diff --git a/pkg/resources/secret_with_oauth_authorization_code_grant.go b/pkg/resources/secret_with_oauth_authorization_code_grant.go
index 97025a1bc8..1797d51e8c 100644
--- a/pkg/resources/secret_with_oauth_authorization_code_grant.go
+++ b/pkg/resources/secret_with_oauth_authorization_code_grant.go
@@ -54,9 +54,9 @@ func SecretWithAuthorizationCodeGrant() *schema.Resource {
},
CustomizeDiff: customdiff.All(
- ComputedIfAnyAttributeChanged(secretAuthorizationCodeGrantSchema, DescribeOutputAttributeName, "name", "oauth_refresh_token_expiry_time", "api_authentication"),
- ComputedIfAnyAttributeChanged(secretAuthorizationCodeGrantSchema, ShowOutputAttributeName, "name", "comment"),
- ComputedIfAnyAttributeChanged(secretAuthorizationCodeGrantSchema, FullyQualifiedNameAttributeName, "name"),
+ ComputedIfAnyAttributeChanged(secretAuthorizationCodeGrantSchema, ShowOutputAttributeName, "comment"),
+ ComputedIfAnyAttributeChanged(secretAuthorizationCodeGrantSchema, DescribeOutputAttributeName, "oauth_refresh_token_expiry_time", "api_authentication"),
+ RecreateWhenSecretTypeChangedExternally(sdk.SecretTypeOAuth2AuthorizationCodeGrant),
),
}
}
@@ -141,32 +141,27 @@ func ReadContextSecretWithAuthorizationCodeGrant(withExternalChangesMarking bool
},
}
}
+
secretDescription, err := client.Secrets.Describe(ctx, id)
if err != nil {
return diag.FromErr(err)
}
- if withExternalChangesMarking {
- if err = handleExternalValueChangesToObjectInDescribe(d,
- describeMapping{"oauth_refresh_token_expiry_time", "oauth_refresh_token_expiry_time", secretDescription.OauthRefreshTokenExpiryTime.String(), secretDescription.OauthRefreshTokenExpiryTime.String(), nil},
+ // if secret type is changed externally, we wont be able to read oauth_refresh_token_expiry_time value (since it will not be provided)
+ // in any other case, there should be oauth_refresh_token_expiry_time value since it is required
+ if withExternalChangesMarking && secretDescription.OauthRefreshTokenExpiryTime != nil {
+ if err = handleExternalChangesToObjectInFlatDescribe(d,
+ outputMapping{"oauth_refresh_token_expiry_time", "oauth_refresh_token_expiry_time", secretDescription.OauthRefreshTokenExpiryTime.String(), secretDescription.OauthRefreshTokenExpiryTime.String(), nil},
); err != nil {
return diag.FromErr(err)
}
}
- if err = setStateToValuesFromConfig(d, secretAuthorizationCodeGrantSchema, []string{"oauth_refresh_token_expiry_time"}); err != nil {
- return diag.FromErr(err)
- }
-
- if err = d.Set("api_authentication", secretDescription.IntegrationName); err != nil {
- return diag.FromErr(err)
- }
-
- if err := handleSecretRead(d, id, secret, secretDescription); err != nil {
- return diag.FromErr(err)
- }
-
- return nil
+ return diag.FromErr(errors.Join(
+ handleSecretRead(d, id, secret, secretDescription),
+ setStateToValuesFromConfig(d, secretAuthorizationCodeGrantSchema, []string{"oauth_refresh_token_expiry_time"}),
+ d.Set("api_authentication", secretDescription.IntegrationName),
+ ))
}
}
diff --git a/pkg/resources/secret_with_oauth_authorization_code_grant_acceptance_test.go b/pkg/resources/secret_with_oauth_authorization_code_grant_acceptance_test.go
index b8f6373a46..82d8c163aa 100644
--- a/pkg/resources/secret_with_oauth_authorization_code_grant_acceptance_test.go
+++ b/pkg/resources/secret_with_oauth_authorization_code_grant_acceptance_test.go
@@ -56,7 +56,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_BasicFlow(t *testing.T) {
Config: config.FromModel(t, secretModel),
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretModel.ResourceReference()).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModel.ResourceReference()).
HasNameString(name).
HasDatabaseString(id.DatabaseName()).
HasSchemaString(id.SchemaName()).
@@ -68,7 +68,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_BasicFlow(t *testing.T) {
resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
HasName(name).
HasDatabaseName(id.DatabaseName()).
- HasSecretType(sdk.SecretTypeOAuth2).
+ HasSecretType(string(sdk.SecretTypeOAuth2)).
HasSchemaName(id.SchemaName()).
HasComment(""),
),
@@ -78,7 +78,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_BasicFlow(t *testing.T) {
resource.TestCheckResourceAttr(secretName, "describe_output.0.name", name),
resource.TestCheckResourceAttr(secretName, "describe_output.0.database_name", id.DatabaseName()),
resource.TestCheckResourceAttr(secretName, "describe_output.0.schema_name", id.SchemaName()),
- resource.TestCheckResourceAttr(secretName, "describe_output.0.secret_type", sdk.SecretTypeOAuth2),
+ resource.TestCheckResourceAttr(secretName, "describe_output.0.secret_type", string(sdk.SecretTypeOAuth2)),
resource.TestCheckResourceAttr(secretName, "describe_output.0.integration_name", integrationId.Name()),
resource.TestCheckResourceAttr(secretName, "describe_output.0.username", ""),
resource.TestCheckResourceAttr(secretName, "describe_output.0.oauth_access_token_expiry_time", ""),
@@ -99,7 +99,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_BasicFlow(t *testing.T) {
},
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretName).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretName).
HasNameString(name).
HasDatabaseString(id.DatabaseName()).
HasSchemaString(id.SchemaName()).
@@ -109,7 +109,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_BasicFlow(t *testing.T) {
HasCommentString(comment),
resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
- HasSecretType(sdk.SecretTypeOAuth2).
+ HasSecretType(string(sdk.SecretTypeOAuth2)).
HasComment(comment),
),
resource.TestCheckResourceAttrSet(secretName, "describe_output.0.oauth_refresh_token_expiry_time"),
@@ -138,7 +138,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_BasicFlow(t *testing.T) {
},
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretName).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretName).
HasNameString(name).
HasDatabaseString(id.DatabaseName()).
HasSchemaString(id.SchemaName()).
@@ -157,7 +157,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_BasicFlow(t *testing.T) {
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"oauth_refresh_token"},
ImportStateCheck: assert.AssertThatImport(t,
- resourceassert.ImportedSecretWithAuthorizationCodeResource(t, helpers.EncodeResourceIdentifier(id)).
+ resourceassert.ImportedSecretWithAuthorizationCodeGrantResource(t, helpers.EncodeResourceIdentifier(id)).
HasNameString(id.Name()).
HasDatabaseString(id.DatabaseName()).
HasSchemaString(id.SchemaName()).
@@ -203,7 +203,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_DifferentTimeFormats(t *testing.T)
Config: config.FromModel(t, secretModelDateOnly),
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretModelDateOnly.ResourceReference()).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModelDateOnly.ResourceReference()).
HasOauthRefreshTokenExpiryTimeString(refreshTokenExpiryDateOnly),
assert.Check(resource.TestCheckResourceAttrSet(secretModelDateOnly.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time")),
),
@@ -214,7 +214,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_DifferentTimeFormats(t *testing.T)
Config: config.FromModel(t, secretModelWithoutSeconds),
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretModelWithoutSeconds.ResourceReference()).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModelWithoutSeconds.ResourceReference()).
HasOauthRefreshTokenExpiryTimeString(refreshTokenExpiryWithoutSeconds),
assert.Check(resource.TestCheckResourceAttrSet(secretModelWithoutSeconds.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time")),
),
@@ -225,7 +225,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_DifferentTimeFormats(t *testing.T)
Config: config.FromModel(t, secretModelDateTime),
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretModelDateTime.ResourceReference()).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModelDateTime.ResourceReference()).
HasOauthRefreshTokenExpiryTimeString(refreshTokenExpiryDateTime),
assert.Check(resource.TestCheckResourceAttrSet(secretModelDateTime.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time")),
),
@@ -236,7 +236,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_DifferentTimeFormats(t *testing.T)
Config: config.FromModel(t, secretModelWithPDT),
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretModelWithPDT.ResourceReference()).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModelWithPDT.ResourceReference()).
HasOauthRefreshTokenExpiryTimeString(refreshTokenExpiryWithPDT),
assert.Check(resource.TestCheckResourceAttrSet(secretModelWithPDT.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time")),
),
@@ -246,7 +246,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_DifferentTimeFormats(t *testing.T)
})
}
-func TestAcc_SecretWithAuthorizationCodeGrant_ExternalChange(t *testing.T) {
+func TestAcc_SecretWithAuthorizationCodeGrant_ExternalRefreshTokenExpiryTimeChange(t *testing.T) {
id := acc.TestClient().Ids.RandomSchemaObjectIdentifier()
name := id.Name()
comment := random.Comment()
@@ -275,7 +275,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_ExternalChange(t *testing.T) {
Config: config.FromModel(t, secretModel),
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretModel.ResourceReference()).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModel.ResourceReference()).
HasNameString(name).
HasDatabaseString(id.DatabaseName()).
HasSchemaString(id.SchemaName()).
@@ -287,7 +287,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_ExternalChange(t *testing.T) {
resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
HasName(name).
HasDatabaseName(id.DatabaseName()).
- HasSecretType(sdk.SecretTypeOAuth2).
+ HasSecretType(string(sdk.SecretTypeOAuth2)).
HasSchemaName(id.SchemaName()).
HasComment(comment),
),
@@ -314,7 +314,7 @@ func TestAcc_SecretWithAuthorizationCodeGrant_ExternalChange(t *testing.T) {
},
Check: resource.ComposeTestCheckFunc(
assert.AssertThat(t,
- resourceassert.SecretWithAuthorizationCodeResource(t, secretModel.ResourceReference()).
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModel.ResourceReference()).
HasOauthRefreshTokenExpiryTimeString(refreshTokenExpiryDateTime),
assert.Check(resource.TestCheckResourceAttrSet(secretModel.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time")),
),
@@ -323,3 +323,124 @@ func TestAcc_SecretWithAuthorizationCodeGrant_ExternalChange(t *testing.T) {
},
})
}
+
+func TestAcc_SecretWithAuthorizationCodeGrant_ExternalSecretTypeChange(t *testing.T) {
+ id := acc.TestClient().Ids.RandomSchemaObjectIdentifier()
+ name := id.Name()
+
+ integrationId := acc.TestClient().Ids.RandomAccountObjectIdentifier()
+ _, apiIntegrationCleanup := acc.TestClient().SecurityIntegration.CreateApiAuthenticationClientCredentialsWithRequest(t,
+ sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"),
+ )
+ t.Cleanup(apiIntegrationCleanup)
+
+ secretModel := model.SecretWithAuthorizationCodeGrant("s", integrationId.Name(), id.DatabaseName(), id.SchemaName(), name, "test_refresh_token", time.Now().Add(24*time.Hour).Format(time.DateOnly))
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories,
+ PreCheck: func() { acc.TestAccPreCheck(t) },
+ TerraformVersionChecks: []tfversion.TerraformVersionCheck{
+ tfversion.RequireAbove(tfversion.Version1_5_0),
+ },
+ CheckDestroy: acc.CheckDestroy(t, resources.SecretWithAuthorizationCodeGrant),
+ Steps: []resource.TestStep{
+ // create
+ {
+ Config: config.FromModel(t, secretModel),
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ ),
+ },
+ // create or replace with different secret type
+ {
+ PreConfig: func() {
+ acc.TestClient().Secret.DropFunc(t, id)()
+ _, cleanup := acc.TestClient().Secret.CreateWithBasicAuthenticationFlow(t, id, "test_pswd", "test_usr")
+ t.Cleanup(cleanup)
+ },
+ Config: config.FromModel(t, secretModel),
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectResourceAction(secretModel.ResourceReference(), plancheck.ResourceActionDestroyBeforeCreate),
+ },
+ },
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ ),
+ },
+ },
+ })
+}
+
+func TestAcc_SecretWithAuthorizationCodeGrant_ExternalSecretTypeChangeToOAuthClientCredentials(t *testing.T) {
+ id := acc.TestClient().Ids.RandomSchemaObjectIdentifier()
+ name := id.Name()
+
+ integrationId := acc.TestClient().Ids.RandomAccountObjectIdentifier()
+ _, apiIntegrationCleanup := acc.TestClient().SecurityIntegration.CreateApiAuthenticationClientCredentialsWithRequest(t,
+ sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "test_client_id", "test_client_secret").
+ WithOauthAllowedScopes([]sdk.AllowedScope{{Scope: "foo"}, {Scope: "bar"}, {Scope: "test"}}),
+ )
+ t.Cleanup(apiIntegrationCleanup)
+
+ secretModel := model.SecretWithAuthorizationCodeGrant("s", integrationId.Name(), id.DatabaseName(), id.SchemaName(), name, "test_refresh_token", time.Now().Add(24*time.Hour).Format(time.DateOnly))
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories,
+ PreCheck: func() { acc.TestAccPreCheck(t) },
+ TerraformVersionChecks: []tfversion.TerraformVersionCheck{
+ tfversion.RequireAbove(tfversion.Version1_5_0),
+ },
+ CheckDestroy: acc.CheckDestroy(t, resources.SecretWithClientCredentials),
+ Steps: []resource.TestStep{
+ // create
+ {
+ Config: config.FromModel(t, secretModel),
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ resource.TestCheckResourceAttrSet(secretModel.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time"),
+ resource.TestCheckResourceAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.#", "0"),
+ ),
+ },
+ // create or replace with same secret type, but different create flow
+ {
+ PreConfig: func() {
+ acc.TestClient().Secret.DropFunc(t, id)()
+ _, cleanup := acc.TestClient().Secret.CreateWithOAuthClientCredentialsFlow(t, id, integrationId, []sdk.ApiIntegrationScope{})
+ t.Cleanup(cleanup)
+ },
+ Config: config.FromModel(t, secretModel),
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectResourceAction(secretModel.ResourceReference(), plancheck.ResourceActionDestroyBeforeCreate),
+ },
+ },
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithAuthorizationCodeGrantResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ resource.TestCheckResourceAttrSet(secretModel.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time"),
+ resource.TestCheckResourceAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.#", "0"),
+ ),
+ },
+ },
+ })
+}
diff --git a/pkg/resources/secret_with_oauth_client_credentials.go b/pkg/resources/secret_with_oauth_client_credentials.go
index 1a387efe0e..866083688d 100644
--- a/pkg/resources/secret_with_oauth_client_credentials.go
+++ b/pkg/resources/secret_with_oauth_client_credentials.go
@@ -43,9 +43,9 @@ func SecretWithClientCredentials() *schema.Resource {
Description: "Resource used to manage secret objects with OAuth Client Credentials. For more information, check [secret documentation](https://docs.snowflake.com/en/sql-reference/sql/create-secret).",
CustomizeDiff: customdiff.All(
- ComputedIfAnyAttributeChanged(secretClientCredentialsSchema, DescribeOutputAttributeName, "name", "oauth_scopes", "api_authentication"),
- ComputedIfAnyAttributeChanged(secretClientCredentialsSchema, ShowOutputAttributeName, "name", "comment"),
- ComputedIfAnyAttributeChanged(secretClientCredentialsSchema, FullyQualifiedNameAttributeName, "name"),
+ ComputedIfAnyAttributeChanged(secretClientCredentialsSchema, DescribeOutputAttributeName, "oauth_scopes", "api_authentication"),
+ ComputedIfAnyAttributeChanged(secretClientCredentialsSchema, ShowOutputAttributeName, "comment"),
+ RecreateWhenSecretTypeChangedExternally(sdk.SecretTypeOAuth2ClientCredentials),
),
Schema: secretClientCredentialsSchema,
diff --git a/pkg/resources/secret_with_oauth_client_credentials_acceptance_test.go b/pkg/resources/secret_with_oauth_client_credentials_acceptance_test.go
index 265f479d1c..69a46330f2 100644
--- a/pkg/resources/secret_with_oauth_client_credentials_acceptance_test.go
+++ b/pkg/resources/secret_with_oauth_client_credentials_acceptance_test.go
@@ -2,6 +2,7 @@ package resources_test
import (
"testing"
+ "time"
acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert"
@@ -64,7 +65,7 @@ func TestAcc_SecretWithClientCredentials_BasicFlow(t *testing.T) {
resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
HasName(name).
HasDatabaseName(id.DatabaseName()).
- HasSecretType(sdk.SecretTypeOAuth2).
+ HasSecretType(string(sdk.SecretTypeOAuth2)).
HasSchemaName(id.SchemaName()),
),
resource.TestCheckResourceAttr(secretName, "oauth_scopes.#", "2"),
@@ -107,7 +108,7 @@ func TestAcc_SecretWithClientCredentials_BasicFlow(t *testing.T) {
assert.Check(resource.TestCheckTypeSetElemAttr(secretName, "oauth_scopes.*", "test")),
resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
- HasSecretType(sdk.SecretTypeOAuth2).
+ HasSecretType(string(sdk.SecretTypeOAuth2)).
HasComment(newComment),
),
@@ -297,3 +298,129 @@ func TestAcc_SecretWithClientCredentials_EmptyScopesList(t *testing.T) {
},
})
}
+
+func TestAcc_SecretWithClientCredentials_ExternalSecretTypeChange(t *testing.T) {
+ id := acc.TestClient().Ids.RandomSchemaObjectIdentifier()
+ name := id.Name()
+
+ integrationId := acc.TestClient().Ids.RandomAccountObjectIdentifier()
+ _, apiIntegrationCleanup := acc.TestClient().SecurityIntegration.CreateApiAuthenticationClientCredentialsWithRequest(t,
+ sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "test_client_id", "test_client_secret").
+ WithOauthAllowedScopes([]sdk.AllowedScope{{Scope: "foo"}, {Scope: "bar"}, {Scope: "test"}}),
+ )
+ t.Cleanup(apiIntegrationCleanup)
+
+ secretModel := model.SecretWithClientCredentials("s", integrationId.Name(), id.DatabaseName(), id.SchemaName(), name, []string{"foo", "bar"})
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories,
+ PreCheck: func() { acc.TestAccPreCheck(t) },
+ TerraformVersionChecks: []tfversion.TerraformVersionCheck{
+ tfversion.RequireAbove(tfversion.Version1_5_0),
+ },
+ CheckDestroy: acc.CheckDestroy(t, resources.SecretWithClientCredentials),
+ Steps: []resource.TestStep{
+ // create
+ {
+ Config: config.FromModel(t, secretModel),
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithClientCredentialsResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ ),
+ },
+ // create or replace with different secret type
+ {
+ PreConfig: func() {
+ acc.TestClient().Secret.DropFunc(t, id)()
+ _, cleanup := acc.TestClient().Secret.CreateWithGenericString(t, id, "test_secret_string")
+ t.Cleanup(cleanup)
+ },
+ Config: config.FromModel(t, secretModel),
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectResourceAction(secretModel.ResourceReference(), plancheck.ResourceActionDestroyBeforeCreate),
+ },
+ },
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithClientCredentialsResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ ),
+ },
+ },
+ })
+}
+
+func TestAcc_SecretWithClientCredentials_ExternalSecretTypeChangeToOAuthAuthCodeGrant(t *testing.T) {
+ id := acc.TestClient().Ids.RandomSchemaObjectIdentifier()
+ name := id.Name()
+
+ integrationId := acc.TestClient().Ids.RandomAccountObjectIdentifier()
+ _, apiIntegrationCleanup := acc.TestClient().SecurityIntegration.CreateApiAuthenticationClientCredentialsWithRequest(t,
+ sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "test_client_id", "test_client_secret").
+ WithOauthAllowedScopes([]sdk.AllowedScope{{Scope: "foo"}, {Scope: "bar"}, {Scope: "test"}}),
+ )
+ t.Cleanup(apiIntegrationCleanup)
+
+ secretModel := model.SecretWithClientCredentials("s", integrationId.Name(), id.DatabaseName(), id.SchemaName(), name, []string{"foo", "bar"})
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories,
+ PreCheck: func() { acc.TestAccPreCheck(t) },
+ TerraformVersionChecks: []tfversion.TerraformVersionCheck{
+ tfversion.RequireAbove(tfversion.Version1_5_0),
+ },
+ CheckDestroy: acc.CheckDestroy(t, resources.SecretWithClientCredentials),
+ Steps: []resource.TestStep{
+ // create
+ {
+ Config: config.FromModel(t, secretModel),
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithClientCredentialsResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ resource.TestCheckResourceAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.#", "2"),
+ resource.TestCheckTypeSetElemAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.*", "foo"),
+ resource.TestCheckTypeSetElemAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.*", "bar"),
+ resource.TestCheckResourceAttr(secretModel.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time", ""),
+ ),
+ },
+ // create or replace with the same secret type but different flow
+ {
+ PreConfig: func() {
+ acc.TestClient().Secret.DropFunc(t, id)()
+ _, cleanup := acc.TestClient().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id, integrationId, "test_refresh_token", time.Now().Add(24*time.Hour).Format(time.DateOnly))
+ t.Cleanup(cleanup)
+ },
+ Config: config.FromModel(t, secretModel),
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectResourceAction(secretModel.ResourceReference(), plancheck.ResourceActionDestroyBeforeCreate),
+ },
+ },
+ Check: resource.ComposeTestCheckFunc(
+ assert.AssertThat(t,
+ resourceassert.SecretWithClientCredentialsResource(t, secretModel.ResourceReference()).
+ HasSecretTypeString(string(sdk.SecretTypeOAuth2)),
+ resourceshowoutputassert.SecretShowOutput(t, secretModel.ResourceReference()).
+ HasSecretType(string(sdk.SecretTypeOAuth2)),
+ ),
+ resource.TestCheckResourceAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.#", "2"),
+ resource.TestCheckTypeSetElemAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.*", "foo"),
+ resource.TestCheckTypeSetElemAttr(secretModel.ResourceReference(), "describe_output.0.oauth_scopes.*", "bar"),
+ resource.TestCheckResourceAttr(secretModel.ResourceReference(), "describe_output.0.oauth_refresh_token_expiry_time", ""),
+ ),
+ },
+ },
+ })
+}
diff --git a/pkg/resources/show_and_describe_handlers.go b/pkg/resources/show_and_describe_handlers.go
index b915b82345..fbbf8e49ca 100644
--- a/pkg/resources/show_and_describe_handlers.go
+++ b/pkg/resources/show_and_describe_handlers.go
@@ -13,14 +13,13 @@ const (
RelatedParametersAttributeName = "related_parameters"
)
-// handleExternalChangesToObjectInShow assumes that show output is kept in ShowOutputAttributeName attribute
-func handleExternalChangesToObjectInShow(d *schema.ResourceData, mappings ...showMapping) error {
- if showOutput, ok := d.GetOk(ShowOutputAttributeName); ok {
- showOutputList := showOutput.([]any)
- if len(showOutputList) == 1 {
- result := showOutputList[0].(map[string]any)
+func handleExternalChangesToObject(d *schema.ResourceData, outputAttributeName string, mappings ...outputMapping) error {
+ if output, ok := d.GetOk(outputAttributeName); ok {
+ outputList := output.([]any)
+ if len(outputList) == 1 {
+ result := outputList[0].(map[string]any)
for _, mapping := range mappings {
- valueToCompareFrom := result[mapping.nameInShow]
+ valueToCompareFrom := result[mapping.nameInOutput]
if mapping.normalizeFunc != nil {
valueToCompareFrom = mapping.normalizeFunc(valueToCompareFrom)
}
@@ -35,36 +34,26 @@ func handleExternalChangesToObjectInShow(d *schema.ResourceData, mappings ...sho
return nil
}
-type showMapping struct {
- nameInShow string
+// handleExternalChangesToObjectInShow assumes that show output is kept in ShowOutputAttributeName attribute
+func handleExternalChangesToObjectInShow(d *schema.ResourceData, mappings ...outputMapping) error {
+ return handleExternalChangesToObject(d, ShowOutputAttributeName, mappings...)
+}
+
+// handleExternalChangesToObjectInFlatDescribe assumes that describe output is kept in DescribeOutputAttributeName attribute
+// It is to be used with flat - show like describe_output schemas
+// To handle external changes to describe with properties like collections use `handleExternalChangesToObjectInDescribe()`
+func handleExternalChangesToObjectInFlatDescribe(d *schema.ResourceData, mappings ...outputMapping) error {
+ return handleExternalChangesToObject(d, DescribeOutputAttributeName, mappings...)
+}
+
+type outputMapping struct {
+ nameInOutput string
nameInConfig string
valueToCompare any
valueToSet any
normalizeFunc func(any) any
}
-// handleExternalValueChangesToObjectInDescribe assumes that describe output is kept in DescribeOutputAttributeName attribute
-func handleExternalValueChangesToObjectInDescribe(d *schema.ResourceData, mappings ...describeMapping) error {
- if descOutput, ok := d.GetOk(DescribeOutputAttributeName); ok {
- descOutputList := descOutput.([]any)
- if len(descOutputList) == 1 {
- result := descOutputList[0].(map[string]any)
- for _, mapping := range mappings {
- valueToCompareFrom := result[mapping.nameInDescribe]
- if mapping.normalizeFunc != nil {
- valueToCompareFrom = mapping.normalizeFunc(valueToCompareFrom)
- }
- if valueToCompareFrom != mapping.valueToCompare {
- if err := d.Set(mapping.nameInConfig, mapping.valueToSet); err != nil {
- return err
- }
- }
- }
- }
- }
- return nil
-}
-
// handleExternalChangesToObjectInDescribe assumes that show output is kept in DescribeOutputAttributeName attribute
func handleExternalChangesToObjectInDescribe(d *schema.ResourceData, mappings ...describeMapping) error {
if describeOutput, ok := d.GetOk(DescribeOutputAttributeName); ok {
diff --git a/pkg/resources/stream_on_external_table.go b/pkg/resources/stream_on_external_table.go
index 07e002e51a..9262e3595e 100644
--- a/pkg/resources/stream_on_external_table.go
+++ b/pkg/resources/stream_on_external_table.go
@@ -170,7 +170,7 @@ func ReadStreamOnExternalTable(withExternalChangesMarking bool) schema.ReadConte
mode = *stream.Mode
}
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"mode", "insert_only", string(mode), booleanStringFromBool(stream.IsInsertOnly()), nil},
+ outputMapping{"mode", "insert_only", string(mode), booleanStringFromBool(stream.IsInsertOnly()), nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/resources/stream_on_table.go b/pkg/resources/stream_on_table.go
index ca02cec50f..4fdcceba23 100644
--- a/pkg/resources/stream_on_table.go
+++ b/pkg/resources/stream_on_table.go
@@ -178,7 +178,7 @@ func ReadStreamOnTable(withExternalChangesMarking bool) schema.ReadContextFunc {
mode = *stream.Mode
}
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"mode", "append_only", string(mode), booleanStringFromBool(stream.IsAppendOnly()), nil},
+ outputMapping{"mode", "append_only", string(mode), booleanStringFromBool(stream.IsAppendOnly()), nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/resources/user.go b/pkg/resources/user.go
index 29cf25a441..cb4a0cfa6a 100644
--- a/pkg/resources/user.go
+++ b/pkg/resources/user.go
@@ -460,7 +460,7 @@ func GetReadUserFunc(userType sdk.UserType, withExternalChangesMarking bool) sch
}
if withExternalChangesMarking {
- showMappings := []showMapping{
+ showMappings := []outputMapping{
{"login_name", "login_name", u.LoginName, u.LoginName, nil},
{"display_name", "display_name", u.DisplayName, u.DisplayName, nil},
{"disabled", "disabled", u.Disabled, fmt.Sprintf("%t", u.Disabled), nil},
@@ -468,7 +468,7 @@ func GetReadUserFunc(userType sdk.UserType, withExternalChangesMarking bool) sch
{"default_secondary_roles", "default_secondary_roles_option", u.DefaultSecondaryRoles, u.GetSecondaryRolesOption(), nil},
}
if userType == sdk.UserTypePerson || userType == sdk.UserTypeLegacyService {
- showMappings = append(showMappings, showMapping{"must_change_password", "must_change_password", u.MustChangePassword, fmt.Sprintf("%t", u.MustChangePassword), nil})
+ showMappings = append(showMappings, outputMapping{"must_change_password", "must_change_password", u.MustChangePassword, fmt.Sprintf("%t", u.MustChangePassword), nil})
}
if err = handleExternalChangesToObjectInShow(d, showMappings...); err != nil {
return diag.FromErr(err)
diff --git a/pkg/resources/view.go b/pkg/resources/view.go
index ea3b4793ee..7c5b6d680f 100644
--- a/pkg/resources/view.go
+++ b/pkg/resources/view.go
@@ -610,14 +610,14 @@ func ReadView(withExternalChangesMarking bool) schema.ReadContextFunc {
}
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"is_secure", "is_secure", view.IsSecure, booleanStringFromBool(view.IsSecure), nil},
- showMapping{"text", "is_recursive", view.IsRecursive(), booleanStringFromBool(view.IsRecursive()), func(x any) any {
+ outputMapping{"is_secure", "is_secure", view.IsSecure, booleanStringFromBool(view.IsSecure), nil},
+ outputMapping{"text", "is_recursive", view.IsRecursive(), booleanStringFromBool(view.IsRecursive()), func(x any) any {
return strings.Contains(x.(string), "RECURSIVE")
}},
- showMapping{"text", "is_temporary", view.IsTemporary(), booleanStringFromBool(view.IsTemporary()), func(x any) any {
+ outputMapping{"text", "is_temporary", view.IsTemporary(), booleanStringFromBool(view.IsTemporary()), func(x any) any {
return strings.Contains(x.(string), "TEMPORARY")
}},
- showMapping{"change_tracking", "change_tracking", view.IsChangeTracking(), booleanStringFromBool(view.IsChangeTracking()), func(x any) any {
+ outputMapping{"change_tracking", "change_tracking", view.IsChangeTracking(), booleanStringFromBool(view.IsChangeTracking()), func(x any) any {
return x.(string) == "ON"
}},
); err != nil {
diff --git a/pkg/resources/warehouse.go b/pkg/resources/warehouse.go
index a2e4c43e36..15222e5a61 100644
--- a/pkg/resources/warehouse.go
+++ b/pkg/resources/warehouse.go
@@ -391,16 +391,16 @@ func GetReadWarehouseFunc(withExternalChangesMarking bool) schema.ReadContextFun
if withExternalChangesMarking {
if err = handleExternalChangesToObjectInShow(d,
- showMapping{"type", "warehouse_type", string(w.Type), w.Type, nil},
- showMapping{"size", "warehouse_size", string(w.Size), w.Size, nil},
- showMapping{"max_cluster_count", "max_cluster_count", w.MaxClusterCount, w.MaxClusterCount, nil},
- showMapping{"min_cluster_count", "min_cluster_count", w.MinClusterCount, w.MinClusterCount, nil},
- showMapping{"scaling_policy", "scaling_policy", string(w.ScalingPolicy), w.ScalingPolicy, nil},
- showMapping{"auto_suspend", "auto_suspend", w.AutoSuspend, w.AutoSuspend, nil},
- showMapping{"auto_resume", "auto_resume", w.AutoResume, fmt.Sprintf("%t", w.AutoResume), nil},
- showMapping{"resource_monitor", "resource_monitor", w.ResourceMonitor.Name(), w.ResourceMonitor.Name(), nil},
- showMapping{"enable_query_acceleration", "enable_query_acceleration", w.EnableQueryAcceleration, fmt.Sprintf("%t", w.EnableQueryAcceleration), nil},
- showMapping{"query_acceleration_max_scale_factor", "query_acceleration_max_scale_factor", w.QueryAccelerationMaxScaleFactor, w.QueryAccelerationMaxScaleFactor, nil},
+ outputMapping{"type", "warehouse_type", string(w.Type), w.Type, nil},
+ outputMapping{"size", "warehouse_size", string(w.Size), w.Size, nil},
+ outputMapping{"max_cluster_count", "max_cluster_count", w.MaxClusterCount, w.MaxClusterCount, nil},
+ outputMapping{"min_cluster_count", "min_cluster_count", w.MinClusterCount, w.MinClusterCount, nil},
+ outputMapping{"scaling_policy", "scaling_policy", string(w.ScalingPolicy), w.ScalingPolicy, nil},
+ outputMapping{"auto_suspend", "auto_suspend", w.AutoSuspend, w.AutoSuspend, nil},
+ outputMapping{"auto_resume", "auto_resume", w.AutoResume, fmt.Sprintf("%t", w.AutoResume), nil},
+ outputMapping{"resource_monitor", "resource_monitor", w.ResourceMonitor.Name(), w.ResourceMonitor.Name(), nil},
+ outputMapping{"enable_query_acceleration", "enable_query_acceleration", w.EnableQueryAcceleration, fmt.Sprintf("%t", w.EnableQueryAcceleration), nil},
+ outputMapping{"query_acceleration_max_scale_factor", "query_acceleration_max_scale_factor", w.QueryAccelerationMaxScaleFactor, w.QueryAccelerationMaxScaleFactor, nil},
); err != nil {
return diag.FromErr(err)
}
diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go
index 44c80475c6..5ac89932a4 100644
--- a/pkg/sdk/secrets_def.go
+++ b/pkg/sdk/secrets_def.go
@@ -2,17 +2,50 @@ package sdk
import (
"fmt"
+ "strings"
g "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/generator"
)
//go:generate go run ./poc/main.go
+
+type (
+ SecretType string
+)
+
+func ToSecretType(s string) (SecretType, error) {
+ switch strings.ToUpper(s) {
+ case string(SecretTypePassword):
+ return SecretTypePassword, nil
+ case string(SecretTypeOAuth2):
+ return SecretTypeOAuth2, nil
+ case string(SecretTypeGenericString):
+ return SecretTypeGenericString, nil
+ case string(SecretTypeOAuth2ClientCredentials):
+ return SecretTypeOAuth2ClientCredentials, nil
+ case string(SecretTypeOAuth2AuthorizationCodeGrant):
+ return SecretTypeOAuth2AuthorizationCodeGrant, nil
+ default:
+ return "", fmt.Errorf("invalid secret type: %s", s)
+ }
+}
+
const (
- SecretTypePassword = "PASSWORD"
- SecretTypeOAuth2 = "OAUTH2"
- SecretTypeGenericString = "GENERIC_STRING"
+ SecretTypePassword SecretType = "PASSWORD"
+ SecretTypeOAuth2 SecretType = "OAUTH2"
+ SecretTypeGenericString SecretType = "GENERIC_STRING"
+ SecretTypeOAuth2ClientCredentials SecretType = "OAUTH2_CLIENT_CREDENTIALS" // #nosec G101
+ SecretTypeOAuth2AuthorizationCodeGrant SecretType = "OAUTH2_AUTHORIZATION_CODE_GRANT" // #nosec G101
)
+var AcceptableSecretTypes = map[SecretType][]SecretType{
+ SecretTypePassword: {SecretTypePassword},
+ SecretTypeOAuth2: {SecretTypeOAuth2},
+ SecretTypeGenericString: {SecretTypeGenericString},
+ SecretTypeOAuth2ClientCredentials: {SecretTypeOAuth2ClientCredentials, SecretTypeOAuth2},
+ SecretTypeOAuth2AuthorizationCodeGrant: {SecretTypeOAuth2ClientCredentials, SecretTypeOAuth2},
+}
+
var secretDbRow = g.DbStruct("secretDBRow").
Field("created_on", "time.Time").
Field("name", "string").
diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go
index fa8042701c..26a12edad0 100644
--- a/pkg/sdk/testint/secrets_gen_integration_test.go
+++ b/pkg/sdk/testint/secrets_gen_integration_test.go
@@ -75,7 +75,7 @@ func TestInt_Secrets(t *testing.T) {
objectassert.Secret(t, id).
HasName(id.Name()).
HasComment("a").
- HasSecretType(sdk.SecretTypeOAuth2).
+ HasSecretType(string(sdk.SecretTypeOAuth2)).
HasOauthScopes([]string{"foo", "bar"}).
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()),
@@ -87,7 +87,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
Comment: sdk.String("a"),
- SecretType: sdk.SecretTypeOAuth2,
+ SecretType: string(sdk.SecretTypeOAuth2),
OauthScopes: []string{"foo", "bar"},
IntegrationName: sdk.String(integrationId.Name()),
})
@@ -114,7 +114,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypeOAuth2,
+ SecretType: string(sdk.SecretTypeOAuth2),
IntegrationName: sdk.String(integrationId.Name()),
})
})
@@ -164,7 +164,7 @@ func TestInt_Secrets(t *testing.T) {
objectassert.Secret(t, id).
HasName(id.Name()).
HasComment("a").
- HasSecretType(sdk.SecretTypeOAuth2).
+ HasSecretType(string(sdk.SecretTypeOAuth2)).
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()),
)
@@ -174,7 +174,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypeOAuth2,
+ SecretType: string(sdk.SecretTypeOAuth2),
Comment: sdk.String("a"),
OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, refreshTokenExpiryTime),
IntegrationName: sdk.String(integrationId.Name()),
@@ -196,7 +196,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypeOAuth2,
+ SecretType: string(sdk.SecretTypeOAuth2),
OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateTime, refreshTokenWithTime),
IntegrationName: sdk.String(integrationId.Name()),
})
@@ -220,7 +220,7 @@ func TestInt_Secrets(t *testing.T) {
objectassert.SecretFromObject(t, secret).
HasName(id.Name()).
HasComment(comment).
- HasSecretType(sdk.SecretTypePassword).
+ HasSecretType(string(sdk.SecretTypePassword)).
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()),
)
@@ -231,7 +231,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
Comment: sdk.String(comment),
- SecretType: sdk.SecretTypePassword,
+ SecretType: string(sdk.SecretTypePassword),
Username: sdk.String("foo"),
})
})
@@ -250,7 +250,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypePassword,
+ SecretType: string(sdk.SecretTypePassword),
Username: sdk.String(""),
})
})
@@ -273,7 +273,7 @@ func TestInt_Secrets(t *testing.T) {
objectassert.Secret(t, id).
HasName(id.Name()).
HasComment(comment).
- HasSecretType(sdk.SecretTypeGenericString).
+ HasSecretType(string(sdk.SecretTypeGenericString)).
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()),
)
@@ -290,7 +290,7 @@ func TestInt_Secrets(t *testing.T) {
assertions.AssertThat(t,
objectassert.Secret(t, id).
HasName(id.Name()).
- HasSecretType(sdk.SecretTypeGenericString).
+ HasSecretType(string(sdk.SecretTypeGenericString)).
HasDatabaseName(id.DatabaseName()).
HasSchemaName(id.SchemaName()),
)
@@ -320,7 +320,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypeOAuth2,
+ SecretType: string(sdk.SecretTypeOAuth2),
Comment: sdk.String(comment),
OauthScopes: []string{"foo", "bar"},
IntegrationName: sdk.String(integrationId.Name()),
@@ -367,7 +367,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypeOAuth2,
+ SecretType: string(sdk.SecretTypeOAuth2),
Comment: sdk.String(comment),
OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, alteredRefreshTokenExpiryTime),
IntegrationName: sdk.String(integrationId.Name()),
@@ -414,7 +414,7 @@ func TestInt_Secrets(t *testing.T) {
// Cannot check password property since show and describe on secret do not have access to it
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypePassword,
+ SecretType: string(sdk.SecretTypePassword),
Comment: sdk.String(comment),
Username: sdk.String("bar"),
})
@@ -712,7 +712,7 @@ func TestInt_Secrets(t *testing.T) {
assertSecretDetails(details, secretDetails{
Name: id.Name(),
- SecretType: sdk.SecretTypeGenericString,
+ SecretType: string(sdk.SecretTypeGenericString),
})
})
}