From 58d57941293c52f67d69329fd1c65b03d669a6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Thu, 12 Sep 2024 13:24:30 +0200 Subject: [PATCH 01/34] initial secret_def file for sdk --- pkg/sdk/poc/main.go | 1 + pkg/sdk/secrets_def.go | 71 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 pkg/sdk/secrets_def.go diff --git a/pkg/sdk/poc/main.go b/pkg/sdk/poc/main.go index 1d98ea99de..72c675a73f 100644 --- a/pkg/sdk/poc/main.go +++ b/pkg/sdk/poc/main.go @@ -45,6 +45,7 @@ var definitionMapping = map[string]*generator.Interface{ "data_metric_function_references_def.go": sdk.DataMetricFunctionReferenceDef, "external_volumes_def.go": sdk.ExternalVolumesDef, "authentication_policies_def.go": sdk.AuthenticationPoliciesDef, + "secrets_def.go": sdk.SecretsDef, } func main() { diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go new file mode 100644 index 0000000000..99e9b8a751 --- /dev/null +++ b/pkg/sdk/secrets_def.go @@ -0,0 +1,71 @@ +package sdk + +import g "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/generator" + +//go:generate go run ./poc/main.go + +var secretsSecurityIntegrationScopeDef = g.NewQueryStruct("SecurityIntegrationScope").Text("Scope", g.KeywordOptions().SingleQuotes().Required()) + +var SecretsDef = g.NewInterface( + "Secrets", + "Secret", + g.KindOfT[SchemaObjectIdentifier](), +).CustomOperation( + "CreateWithOAuthClientCredentialsFlow", + "https://docs.snowflake.com/en/sql-reference/sql/create-secret", + g.NewQueryStruct("CreateOAuthWithClientCredentialsFlow"). + Create(). + OrReplace(). + SQL("SECRET"). + IfNotExists(). + Name(). + PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). + Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION").Required()). + ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses()). + OptionalComment(). + WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), + secretsSecurityIntegrationScopeDef, +).CustomOperation( + "CreateWithOAuthAuthorizationCode", + "https://docs.snowflake.com/en/sql-reference/sql/create-secret", + g.NewQueryStruct("CreateWithOAuthAuthorizationCode"). + Create(). + OrReplace(). + SQL("SECRET"). + IfNotExists(). + Name(). + PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). + TextAssignment("OAUTH_REFRESH_TOKEN", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). + TextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). + Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). + OptionalComment(). + WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), + secretsSecurityIntegrationScopeDef, +).CustomOperation( + "CreateWithBasicAuthentication", + "https://docs.snowflake.com/en/sql-reference/sql/create-secret", + g.NewQueryStruct("CreateWithBasicAuthentication"). + Create(). + OrReplace(). + SQL("SECRET"). + IfNotExists(). + Name(). + PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = PASSWORD")). + TextAssignment("USERNAME", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). + TextAssignment("PASSWORD", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). + OptionalComment(). + WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), +).CustomOperation( + "CreateWithGenericString", + "https://docs.snowflake.com/en/sql-reference/sql/create-secret", + g.NewQueryStruct("CreateWithGenericString"). + Create(). + OrReplace(). + SQL("SECRET"). + IfNotExists(). + Name(). + PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = GENERIC_STRING")). + TextAssignment("SECRET_STRING", g.ParameterOptions().SingleQuotes().Required()). + OptionalComment(). + WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), +) From f1488ca47330d5fac6fb0a81b2c303e1231219ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Thu, 12 Sep 2024 15:05:13 +0200 Subject: [PATCH 02/34] naming changes to secret create options --- pkg/sdk/secrets_def.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 99e9b8a751..7c50aa41c7 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -13,7 +13,7 @@ var SecretsDef = g.NewInterface( ).CustomOperation( "CreateWithOAuthClientCredentialsFlow", "https://docs.snowflake.com/en/sql-reference/sql/create-secret", - g.NewQueryStruct("CreateOAuthWithClientCredentialsFlow"). + g.NewQueryStruct("CreateWithOAuthClientCredentialsFlow"). Create(). OrReplace(). SQL("SECRET"). @@ -23,12 +23,13 @@ var SecretsDef = g.NewInterface( Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION").Required()). ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses()). OptionalComment(). + WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), secretsSecurityIntegrationScopeDef, ).CustomOperation( - "CreateWithOAuthAuthorizationCode", + "CreateWithOAuthAuthorizationCodeFlow", "https://docs.snowflake.com/en/sql-reference/sql/create-secret", - g.NewQueryStruct("CreateWithOAuthAuthorizationCode"). + g.NewQueryStruct("CreateWithOAuthAuthorizationCodeFlow"). Create(). OrReplace(). SQL("SECRET"). @@ -39,6 +40,7 @@ var SecretsDef = g.NewInterface( TextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). OptionalComment(). + WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), secretsSecurityIntegrationScopeDef, ).CustomOperation( @@ -54,6 +56,7 @@ var SecretsDef = g.NewInterface( TextAssignment("USERNAME", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). TextAssignment("PASSWORD", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). OptionalComment(). + WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), ).CustomOperation( "CreateWithGenericString", @@ -67,5 +70,6 @@ var SecretsDef = g.NewInterface( PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = GENERIC_STRING")). TextAssignment("SECRET_STRING", g.ParameterOptions().SingleQuotes().Required()). OptionalComment(). + WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), ) From 752f92446de873d97b4d55fe8125e9403ef1e478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Fri, 13 Sep 2024 09:54:15 +0200 Subject: [PATCH 03/34] create secrets and alter with two basic tests --- pkg/sdk/secrets_def.go | 39 ++++- pkg/sdk/secrets_dto_builders_gen.go | 196 +++++++++++++++++++++ pkg/sdk/secrets_dto_gen.go | 72 ++++++++ pkg/sdk/secrets_gen.go | 91 ++++++++++ pkg/sdk/secrets_gen_integration_test.go | 27 +++ pkg/sdk/secrets_gen_test.go | 215 ++++++++++++++++++++++++ pkg/sdk/secrets_impl_gen.go | 120 +++++++++++++ pkg/sdk/secrets_validations_gen.go | 76 +++++++++ 8 files changed, 835 insertions(+), 1 deletion(-) create mode 100644 pkg/sdk/secrets_dto_builders_gen.go create mode 100644 pkg/sdk/secrets_dto_gen.go create mode 100644 pkg/sdk/secrets_gen.go create mode 100644 pkg/sdk/secrets_gen_integration_test.go create mode 100644 pkg/sdk/secrets_gen_test.go create mode 100644 pkg/sdk/secrets_impl_gen.go create mode 100644 pkg/sdk/secrets_validations_gen.go diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 7c50aa41c7..e0bdea0f34 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -4,7 +4,25 @@ import g "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/gen //go:generate go run ./poc/main.go -var secretsSecurityIntegrationScopeDef = g.NewQueryStruct("SecurityIntegrationScope").Text("Scope", g.KeywordOptions().SingleQuotes().Required()) +var secretsSecurityIntegrationScopeDef = g.NewQueryStruct("SecurityIntegrationScope"). + Text("Scope", g.KeywordOptions().SingleQuotes().Required()) + +var secretsOAuthScopes = g.NewQueryStruct("OAuthScopes"). + List("OAuthScopes", "SecurityIntegrationScope", g.ListOptions().MustParentheses()) + +var secretSet = g.NewQueryStruct("SecretSet"). + OptionalComment(). + OptionalQueryStructField("OAuthScopes", secretsOAuthScopes, g.ParameterOptions().MustParentheses().SQL("OAUTH_SCOPES")). + OptionalTextAssignment("OAUTH_REFRESH_TOKEN", g.ParameterOptions().SingleQuotes()). + OptionalTextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().SingleQuotes()). + OptionalTextAssignment("USERNAME", g.ParameterOptions().SingleQuotes()). + OptionalTextAssignment("PASSWORD", g.ParameterOptions().SingleQuotes()). + OptionalTextAssignment("SECRET_STRING", g.ParameterOptions().SingleQuotes()) + +// unset doest work, need to use "set comment = null" +// OptionalSQL("SET COMMENT = NULL") +var secretUnset = g.NewQueryStruct("SecretUnset"). + OptionalSQL("UNSET COMMENT") var SecretsDef = g.NewInterface( "Secrets", @@ -22,6 +40,7 @@ var SecretsDef = g.NewInterface( PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION").Required()). ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses()). + //QueryStructField("OAuthScopes", secretsOAuthScopes, g.ParameterOptions().MustParentheses()). OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), @@ -72,4 +91,22 @@ var SecretsDef = g.NewInterface( OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), +).AlterOperation( + "https://docs.snowflake.com/en/sql-reference/sql/alter-secret", + g.NewQueryStruct("AlterSecret"). + Alter(). + SQL("SECRET"). + IfExists(). + Name(). + OptionalQueryStructField( + "Set", + secretSet, + g.KeywordOptions().SQL("SET"), + ). + OptionalQueryStructField( + "Unset", + secretUnset, + g.KeywordOptions().SQL("UNSET"), + ). + WithValidation(g.ExactlyOneValueSet, "Set", "Unset"), ) diff --git a/pkg/sdk/secrets_dto_builders_gen.go b/pkg/sdk/secrets_dto_builders_gen.go new file mode 100644 index 0000000000..dc1f083aa3 --- /dev/null +++ b/pkg/sdk/secrets_dto_builders_gen.go @@ -0,0 +1,196 @@ +// Code generated by dto builder generator; DO NOT EDIT. + +package sdk + +import () + +func NewCreateWithOAuthClientCredentialsFlowSecretRequest( + name SchemaObjectIdentifier, + SecurityIntegration AccountObjectIdentifier, +) *CreateWithOAuthClientCredentialsFlowSecretRequest { + s := CreateWithOAuthClientCredentialsFlowSecretRequest{} + s.name = name + s.SecurityIntegration = SecurityIntegration + return &s +} + +func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithOrReplace(OrReplace bool) *CreateWithOAuthClientCredentialsFlowSecretRequest { + s.OrReplace = &OrReplace + return s +} + +func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithIfNotExists(IfNotExists bool) *CreateWithOAuthClientCredentialsFlowSecretRequest { + s.IfNotExists = &IfNotExists + return s +} + +func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithOauthScopes(OauthScopes []SecurityIntegrationScope) *CreateWithOAuthClientCredentialsFlowSecretRequest { + s.OauthScopes = OauthScopes + return s +} + +func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithComment(Comment string) *CreateWithOAuthClientCredentialsFlowSecretRequest { + s.Comment = &Comment + return s +} + +func NewCreateWithOAuthAuthorizationCodeFlowSecretRequest( + name SchemaObjectIdentifier, + OauthRefreshToken string, + OauthRefreshTokenExpiryTime string, + SecurityIntegration AccountObjectIdentifier, +) *CreateWithOAuthAuthorizationCodeFlowSecretRequest { + s := CreateWithOAuthAuthorizationCodeFlowSecretRequest{} + s.name = name + s.OauthRefreshToken = OauthRefreshToken + s.OauthRefreshTokenExpiryTime = OauthRefreshTokenExpiryTime + s.SecurityIntegration = SecurityIntegration + return &s +} + +func (s *CreateWithOAuthAuthorizationCodeFlowSecretRequest) WithOrReplace(OrReplace bool) *CreateWithOAuthAuthorizationCodeFlowSecretRequest { + s.OrReplace = &OrReplace + return s +} + +func (s *CreateWithOAuthAuthorizationCodeFlowSecretRequest) WithIfNotExists(IfNotExists bool) *CreateWithOAuthAuthorizationCodeFlowSecretRequest { + s.IfNotExists = &IfNotExists + return s +} + +func (s *CreateWithOAuthAuthorizationCodeFlowSecretRequest) WithComment(Comment string) *CreateWithOAuthAuthorizationCodeFlowSecretRequest { + s.Comment = &Comment + return s +} + +func NewCreateWithBasicAuthenticationSecretRequest( + name SchemaObjectIdentifier, + Username string, + Password string, +) *CreateWithBasicAuthenticationSecretRequest { + s := CreateWithBasicAuthenticationSecretRequest{} + s.name = name + s.Username = Username + s.Password = Password + return &s +} + +func (s *CreateWithBasicAuthenticationSecretRequest) WithOrReplace(OrReplace bool) *CreateWithBasicAuthenticationSecretRequest { + s.OrReplace = &OrReplace + return s +} + +func (s *CreateWithBasicAuthenticationSecretRequest) WithIfNotExists(IfNotExists bool) *CreateWithBasicAuthenticationSecretRequest { + s.IfNotExists = &IfNotExists + return s +} + +func (s *CreateWithBasicAuthenticationSecretRequest) WithComment(Comment string) *CreateWithBasicAuthenticationSecretRequest { + s.Comment = &Comment + return s +} + +func NewCreateWithGenericStringSecretRequest( + name SchemaObjectIdentifier, + SecretString string, +) *CreateWithGenericStringSecretRequest { + s := CreateWithGenericStringSecretRequest{} + s.name = name + s.SecretString = SecretString + return &s +} + +func (s *CreateWithGenericStringSecretRequest) WithOrReplace(OrReplace bool) *CreateWithGenericStringSecretRequest { + s.OrReplace = &OrReplace + return s +} + +func (s *CreateWithGenericStringSecretRequest) WithIfNotExists(IfNotExists bool) *CreateWithGenericStringSecretRequest { + s.IfNotExists = &IfNotExists + return s +} + +func (s *CreateWithGenericStringSecretRequest) WithComment(Comment string) *CreateWithGenericStringSecretRequest { + s.Comment = &Comment + return s +} + +func NewAlterSecretRequest( + name SchemaObjectIdentifier, +) *AlterSecretRequest { + s := AlterSecretRequest{} + s.name = name + return &s +} + +func (s *AlterSecretRequest) WithIfExists(IfExists bool) *AlterSecretRequest { + s.IfExists = &IfExists + return s +} + +func (s *AlterSecretRequest) WithSet(Set SecretSetRequest) *AlterSecretRequest { + s.Set = &Set + return s +} + +func (s *AlterSecretRequest) WithUnset(Unset SecretUnsetRequest) *AlterSecretRequest { + s.Unset = &Unset + return s +} + +func NewSecretSetRequest() *SecretSetRequest { + return &SecretSetRequest{} +} + +func (s *SecretSetRequest) WithComment(Comment string) *SecretSetRequest { + s.Comment = &Comment + return s +} + +func (s *SecretSetRequest) WithOAuthScopes(OAuthScopes OAuthScopesRequest) *SecretSetRequest { + s.OAuthScopes = &OAuthScopes + return s +} + +func (s *SecretSetRequest) WithOauthRefreshToken(OauthRefreshToken string) *SecretSetRequest { + s.OauthRefreshToken = &OauthRefreshToken + return s +} + +func (s *SecretSetRequest) WithOauthRefreshTokenExpiryTime(OauthRefreshTokenExpiryTime string) *SecretSetRequest { + s.OauthRefreshTokenExpiryTime = &OauthRefreshTokenExpiryTime + return s +} + +func (s *SecretSetRequest) WithUsername(Username string) *SecretSetRequest { + s.Username = &Username + return s +} + +func (s *SecretSetRequest) WithPassword(Password string) *SecretSetRequest { + s.Password = &Password + return s +} + +func (s *SecretSetRequest) WithSecretString(SecretString string) *SecretSetRequest { + s.SecretString = &SecretString + return s +} + +func NewOAuthScopesRequest() *OAuthScopesRequest { + return &OAuthScopesRequest{} +} + +func (s *OAuthScopesRequest) WithOAuthScopes(OAuthScopes []SecurityIntegrationScope) *OAuthScopesRequest { + s.OAuthScopes = OAuthScopes + return s +} + +func NewSecretUnsetRequest() *SecretUnsetRequest { + return &SecretUnsetRequest{} +} + +func (s *SecretUnsetRequest) WithUnsetComment(UnsetComment bool) *SecretUnsetRequest { + s.UnsetComment = &UnsetComment + return s +} diff --git a/pkg/sdk/secrets_dto_gen.go b/pkg/sdk/secrets_dto_gen.go new file mode 100644 index 0000000000..5f37d8caf0 --- /dev/null +++ b/pkg/sdk/secrets_dto_gen.go @@ -0,0 +1,72 @@ +package sdk + +//go:generate go run ./dto-builder-generator/main.go + +var ( + _ optionsProvider[CreateWithOAuthClientCredentialsFlowSecretOptions] = new(CreateWithOAuthClientCredentialsFlowSecretRequest) + _ optionsProvider[CreateWithOAuthAuthorizationCodeFlowSecretOptions] = new(CreateWithOAuthAuthorizationCodeFlowSecretRequest) + _ optionsProvider[CreateWithBasicAuthenticationSecretOptions] = new(CreateWithBasicAuthenticationSecretRequest) + _ optionsProvider[CreateWithGenericStringSecretOptions] = new(CreateWithGenericStringSecretRequest) + _ optionsProvider[AlterSecretOptions] = new(AlterSecretRequest) +) + +type CreateWithOAuthClientCredentialsFlowSecretRequest struct { + OrReplace *bool + IfNotExists *bool + name SchemaObjectIdentifier // required + SecurityIntegration AccountObjectIdentifier // required + OauthScopes []SecurityIntegrationScope + Comment *string +} + +type CreateWithOAuthAuthorizationCodeFlowSecretRequest struct { + OrReplace *bool + IfNotExists *bool + name SchemaObjectIdentifier // required + OauthRefreshToken string // required + OauthRefreshTokenExpiryTime string // required + SecurityIntegration AccountObjectIdentifier // required + Comment *string +} + +type CreateWithBasicAuthenticationSecretRequest struct { + OrReplace *bool + IfNotExists *bool + name SchemaObjectIdentifier // required + Username string // required + Password string // required + Comment *string +} + +type CreateWithGenericStringSecretRequest struct { + OrReplace *bool + IfNotExists *bool + name SchemaObjectIdentifier // required + SecretString string // required + Comment *string +} + +type AlterSecretRequest struct { + IfExists *bool + name SchemaObjectIdentifier // required + Set *SecretSetRequest + Unset *SecretUnsetRequest +} + +type SecretSetRequest struct { + Comment *string + OAuthScopes *OAuthScopesRequest + OauthRefreshToken *string + OauthRefreshTokenExpiryTime *string + Username *string + Password *string + SecretString *string +} + +type OAuthScopesRequest struct { + OAuthScopes []SecurityIntegrationScope +} + +type SecretUnsetRequest struct { + UnsetComment *bool +} diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go new file mode 100644 index 0000000000..9f5ac8638b --- /dev/null +++ b/pkg/sdk/secrets_gen.go @@ -0,0 +1,91 @@ +package sdk + +import "context" + +type Secrets interface { + CreateWithOAuthClientCredentialsFlow(ctx context.Context, request *CreateWithOAuthClientCredentialsFlowSecretRequest) error + CreateWithOAuthAuthorizationCodeFlow(ctx context.Context, request *CreateWithOAuthAuthorizationCodeFlowSecretRequest) error + CreateWithBasicAuthentication(ctx context.Context, request *CreateWithBasicAuthenticationSecretRequest) error + CreateWithGenericString(ctx context.Context, request *CreateWithGenericStringSecretRequest) error + Alter(ctx context.Context, request *AlterSecretRequest) error +} + +// CreateWithOAuthClientCredentialsFlowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-secret. +type CreateWithOAuthClientCredentialsFlowSecretOptions struct { + create bool `ddl:"static" sql:"CREATE"` + OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` + secret bool `ddl:"static" sql:"SECRET"` + IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + Type string `ddl:"static" sql:"TYPE = OAUTH2"` + SecurityIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` + OauthScopes []SecurityIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` +} +type SecurityIntegrationScope struct { + Scope string `ddl:"keyword,single_quotes"` +} + +// CreateWithOAuthAuthorizationCodeFlowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-secret. +type CreateWithOAuthAuthorizationCodeFlowSecretOptions struct { + create bool `ddl:"static" sql:"CREATE"` + OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` + secret bool `ddl:"static" sql:"SECRET"` + IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + Type string `ddl:"static" sql:"TYPE = OAUTH2"` + OauthRefreshToken string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` + OauthRefreshTokenExpiryTime string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN_EXPIRY_TIME"` + SecurityIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` +} + +// CreateWithBasicAuthenticationSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-secret. +type CreateWithBasicAuthenticationSecretOptions struct { + create bool `ddl:"static" sql:"CREATE"` + OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` + secret bool `ddl:"static" sql:"SECRET"` + IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + Type string `ddl:"static" sql:"TYPE = PASSWORD"` + Username string `ddl:"parameter,single_quotes" sql:"USERNAME"` + Password string `ddl:"parameter,single_quotes" sql:"PASSWORD"` + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` +} + +// CreateWithGenericStringSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-secret. +type CreateWithGenericStringSecretOptions struct { + create bool `ddl:"static" sql:"CREATE"` + OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` + secret bool `ddl:"static" sql:"SECRET"` + IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + Type string `ddl:"static" sql:"TYPE = GENERIC_STRING"` + SecretString string `ddl:"parameter,single_quotes" sql:"SECRET_STRING"` + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` +} + +// AlterSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/alter-secret. +type AlterSecretOptions struct { + alter bool `ddl:"static" sql:"ALTER"` + secret bool `ddl:"static" sql:"SECRET"` + IfExists *bool `ddl:"keyword" sql:"IF EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + Set *SecretSet `ddl:"keyword" sql:"SET"` + Unset *SecretUnset `ddl:"keyword" sql:"UNSET"` +} +type SecretSet struct { + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` + OAuthScopes *OAuthScopes `ddl:"parameter,must_parentheses" sql:"OAUTH_SCOPES"` + OauthRefreshToken *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` + OauthRefreshTokenExpiryTime *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN_EXPIRY_TIME"` + Username *string `ddl:"parameter,single_quotes" sql:"USERNAME"` + Password *string `ddl:"parameter,single_quotes" sql:"PASSWORD"` + SecretString *string `ddl:"parameter,single_quotes" sql:"SECRET_STRING"` +} +type OAuthScopes struct { + OAuthScopes []SecurityIntegrationScope `ddl:"list,must_parentheses"` +} +type SecretUnset struct { + UnsetComment *bool `ddl:"keyword" sql:"UNSET COMMENT"` +} diff --git a/pkg/sdk/secrets_gen_integration_test.go b/pkg/sdk/secrets_gen_integration_test.go new file mode 100644 index 0000000000..ee9af4239a --- /dev/null +++ b/pkg/sdk/secrets_gen_integration_test.go @@ -0,0 +1,27 @@ +package sdk + +import "testing" + +func TestInt_Secrets(t *testing.T) { + // TODO: prepare common resources + + t.Run("CreateWithOAuthClientCredentialsFlow", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("CreateWithBasicAuthentication", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("CreateWithGenericString", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Alter", func(t *testing.T) { + // TODO: fill me + }) +} diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go new file mode 100644 index 0000000000..426e5eee09 --- /dev/null +++ b/pkg/sdk/secrets_gen_test.go @@ -0,0 +1,215 @@ +package sdk + +import "testing" + +func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { + + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithOAuthClientCredentialsFlowSecretOptions + defaultOpts := func() *CreateWithOAuthClientCredentialsFlowSecretOptions { + return &CreateWithOAuthClientCredentialsFlowSecretOptions{ + + name: id, + } + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *CreateWithOAuthClientCredentialsFlowSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + + t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthClientCredentialsFlowSecretOptions", "OrReplace", "IfNotExists")) + }) + + t.Run("basic", func(t *testing.T) { + securityIntegration := NewAccountObjectIdentifier("security_integration") + oauthScopes := []SecurityIntegrationScope{{Scope: "sample_scope"}} + + opts := defaultOpts() + opts.SecurityIntegration = securityIntegration + opts.OauthScopes = oauthScopes + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName(), securityIntegration.FullyQualifiedName()) + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} + +func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { + + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithOAuthAuthorizationCodeFlowSecretOptions + defaultOpts := func() *CreateWithOAuthAuthorizationCodeFlowSecretOptions { + return &CreateWithOAuthAuthorizationCodeFlowSecretOptions{ + + name: id, + } + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *CreateWithOAuthAuthorizationCodeFlowSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + + t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthAuthorizationCodeFlowSecretOptions", "OrReplace", "IfNotExists")) + }) + + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} + +func TestSecrets_CreateWithBasicAuthentication(t *testing.T) { + + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithBasicAuthenticationSecretOptions + defaultOpts := func() *CreateWithBasicAuthenticationSecretOptions { + return &CreateWithBasicAuthenticationSecretOptions{ + + name: id, + } + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *CreateWithBasicAuthenticationSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + + t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithBasicAuthenticationSecretOptions", "OrReplace", "IfNotExists")) + }) + + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} + +func TestSecrets_CreateWithGenericString(t *testing.T) { + + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithGenericStringSecretOptions + defaultOpts := func() *CreateWithGenericStringSecretOptions { + return &CreateWithGenericStringSecretOptions{ + + name: id, + } + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *CreateWithGenericStringSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + + t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithGenericStringSecretOptions", "OrReplace", "IfNotExists")) + }) + + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} + +func TestSecrets_Alter(t *testing.T) { + + id := randomSchemaObjectIdentifier() + // Minimal valid AlterSecretOptions + defaultOpts := func() *AlterSecretOptions { + return &AlterSecretOptions{ + + name: id, + } + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *AlterSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + t.Run("validation: exactly one field from [opts.Set opts.Unset] should be present", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) + }) + + t.Run("alter: set options", func(t *testing.T) { + oauthScopes := &OAuthScopes{[]SecurityIntegrationScope{{Scope: "different_scope_name"}}} + + opts := defaultOpts() + opts.Set = &SecretSet{ + OAuthScopes: oauthScopes, + OauthRefreshToken: String("refresh_token"), + OauthRefreshTokenExpiryTime: String("2024-10-10"), + } + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET %s SET OAUTH_SCOPES = ('different_scope_name')", id.FullyQualifiedName()) + }) + + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go new file mode 100644 index 0000000000..bdce5ad21a --- /dev/null +++ b/pkg/sdk/secrets_impl_gen.go @@ -0,0 +1,120 @@ +package sdk + +import ( + "context" +) + +var _ Secrets = (*secrets)(nil) + +type secrets struct { + client *Client +} + +func (v *secrets) CreateWithOAuthClientCredentialsFlow(ctx context.Context, request *CreateWithOAuthClientCredentialsFlowSecretRequest) error { + opts := request.toOpts() + return validateAndExec(v.client, ctx, opts) +} + +func (v *secrets) CreateWithOAuthAuthorizationCodeFlow(ctx context.Context, request *CreateWithOAuthAuthorizationCodeFlowSecretRequest) error { + opts := request.toOpts() + return validateAndExec(v.client, ctx, opts) +} + +func (v *secrets) CreateWithBasicAuthentication(ctx context.Context, request *CreateWithBasicAuthenticationSecretRequest) error { + opts := request.toOpts() + return validateAndExec(v.client, ctx, opts) +} + +func (v *secrets) CreateWithGenericString(ctx context.Context, request *CreateWithGenericStringSecretRequest) error { + opts := request.toOpts() + return validateAndExec(v.client, ctx, opts) +} + +func (v *secrets) Alter(ctx context.Context, request *AlterSecretRequest) error { + opts := request.toOpts() + return validateAndExec(v.client, ctx, opts) +} + +func (r *CreateWithOAuthClientCredentialsFlowSecretRequest) toOpts() *CreateWithOAuthClientCredentialsFlowSecretOptions { + opts := &CreateWithOAuthClientCredentialsFlowSecretOptions{ + OrReplace: r.OrReplace, + IfNotExists: r.IfNotExists, + name: r.name, + SecurityIntegration: r.SecurityIntegration, + OauthScopes: r.OauthScopes, + Comment: r.Comment, + } + return opts +} + +func (r *CreateWithOAuthAuthorizationCodeFlowSecretRequest) toOpts() *CreateWithOAuthAuthorizationCodeFlowSecretOptions { + opts := &CreateWithOAuthAuthorizationCodeFlowSecretOptions{ + OrReplace: r.OrReplace, + IfNotExists: r.IfNotExists, + name: r.name, + OauthRefreshToken: r.OauthRefreshToken, + OauthRefreshTokenExpiryTime: r.OauthRefreshTokenExpiryTime, + SecurityIntegration: r.SecurityIntegration, + Comment: r.Comment, + } + return opts +} + +func (r *CreateWithBasicAuthenticationSecretRequest) toOpts() *CreateWithBasicAuthenticationSecretOptions { + opts := &CreateWithBasicAuthenticationSecretOptions{ + OrReplace: r.OrReplace, + IfNotExists: r.IfNotExists, + name: r.name, + Username: r.Username, + Password: r.Password, + Comment: r.Comment, + } + return opts +} + +func (r *CreateWithGenericStringSecretRequest) toOpts() *CreateWithGenericStringSecretOptions { + opts := &CreateWithGenericStringSecretOptions{ + OrReplace: r.OrReplace, + IfNotExists: r.IfNotExists, + name: r.name, + SecretString: r.SecretString, + Comment: r.Comment, + } + return opts +} + +func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { + opts := &AlterSecretOptions{ + IfExists: r.IfExists, + name: r.name, + } + + if r.Set != nil { + opts.Set = &SecretSet{ + Comment: r.Set.Comment, + + OauthRefreshToken: r.Set.OauthRefreshToken, + OauthRefreshTokenExpiryTime: r.Set.OauthRefreshTokenExpiryTime, + Username: r.Set.Username, + Password: r.Set.Password, + SecretString: r.Set.SecretString, + } + + if r.Set.OAuthScopes != nil { + opts.Set.OAuthScopes = &OAuthScopes{ + OAuthScopes: r.Set.OAuthScopes.OAuthScopes, + } + + } + + } + + if r.Unset != nil { + opts.Unset = &SecretUnset{ + UnsetComment: r.Unset.UnsetComment, + } + + } + + return opts +} diff --git a/pkg/sdk/secrets_validations_gen.go b/pkg/sdk/secrets_validations_gen.go new file mode 100644 index 0000000000..513145bf1c --- /dev/null +++ b/pkg/sdk/secrets_validations_gen.go @@ -0,0 +1,76 @@ +package sdk + +var ( + _ validatable = new(CreateWithOAuthClientCredentialsFlowSecretOptions) + _ validatable = new(CreateWithOAuthAuthorizationCodeFlowSecretOptions) + _ validatable = new(CreateWithBasicAuthenticationSecretOptions) + _ validatable = new(CreateWithGenericStringSecretOptions) + _ validatable = new(AlterSecretOptions) +) + +func (opts *CreateWithOAuthClientCredentialsFlowSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + if !ValidObjectIdentifier(opts.name) { + errs = append(errs, ErrInvalidObjectIdentifier) + } + if everyValueSet(opts.OrReplace, opts.IfNotExists) { + errs = append(errs, errOneOf("CreateWithOAuthClientCredentialsFlowSecretOptions", "OrReplace", "IfNotExists")) + } + return JoinErrors(errs...) +} + +func (opts *CreateWithOAuthAuthorizationCodeFlowSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + if !ValidObjectIdentifier(opts.name) { + errs = append(errs, ErrInvalidObjectIdentifier) + } + if everyValueSet(opts.OrReplace, opts.IfNotExists) { + errs = append(errs, errOneOf("CreateWithOAuthAuthorizationCodeFlowSecretOptions", "OrReplace", "IfNotExists")) + } + return JoinErrors(errs...) +} + +func (opts *CreateWithBasicAuthenticationSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + if !ValidObjectIdentifier(opts.name) { + errs = append(errs, ErrInvalidObjectIdentifier) + } + if everyValueSet(opts.OrReplace, opts.IfNotExists) { + errs = append(errs, errOneOf("CreateWithBasicAuthenticationSecretOptions", "OrReplace", "IfNotExists")) + } + return JoinErrors(errs...) +} + +func (opts *CreateWithGenericStringSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + if !ValidObjectIdentifier(opts.name) { + errs = append(errs, ErrInvalidObjectIdentifier) + } + if everyValueSet(opts.OrReplace, opts.IfNotExists) { + errs = append(errs, errOneOf("CreateWithGenericStringSecretOptions", "OrReplace", "IfNotExists")) + } + return JoinErrors(errs...) +} + +func (opts *AlterSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + if !exactlyOneValueSet(opts.Set, opts.Unset) { + errs = append(errs, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) + } + return JoinErrors(errs...) +} From d7ae12f4325a2e3f02e77a971d8d8b013760b65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Fri, 13 Sep 2024 14:54:15 +0200 Subject: [PATCH 04/34] unit tests for alter --- pkg/sdk/secrets_def.go | 59 +++++++++++++++----- pkg/sdk/secrets_dto_builders_gen.go | 67 +++++++++++++++-------- pkg/sdk/secrets_dto_gen.go | 34 ++++++++---- pkg/sdk/secrets_gen.go | 31 +++++++---- pkg/sdk/secrets_gen_test.go | 85 ++++++++++++++++++++--------- pkg/sdk/secrets_impl_gen.go | 41 +++++++++++--- pkg/sdk/secrets_validations_gen.go | 5 ++ 7 files changed, 229 insertions(+), 93 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index e0bdea0f34..204db83165 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -7,22 +7,49 @@ import g "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/gen var secretsSecurityIntegrationScopeDef = g.NewQueryStruct("SecurityIntegrationScope"). Text("Scope", g.KeywordOptions().SingleQuotes().Required()) -var secretsOAuthScopes = g.NewQueryStruct("OAuthScopes"). +/* +var secretsIntegrationScopes = g.NewQueryStruct("OAuthScopes"). List("OAuthScopes", "SecurityIntegrationScope", g.ListOptions().MustParentheses()) +*/ var secretSet = g.NewQueryStruct("SecretSet"). OptionalComment(). - OptionalQueryStructField("OAuthScopes", secretsOAuthScopes, g.ParameterOptions().MustParentheses().SQL("OAUTH_SCOPES")). - OptionalTextAssignment("OAUTH_REFRESH_TOKEN", g.ParameterOptions().SingleQuotes()). - OptionalTextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().SingleQuotes()). - OptionalTextAssignment("USERNAME", g.ParameterOptions().SingleQuotes()). - OptionalTextAssignment("PASSWORD", g.ParameterOptions().SingleQuotes()). - OptionalTextAssignment("SECRET_STRING", g.ParameterOptions().SingleQuotes()) + OptionalQueryStructField( + "SetForOAuthClientCredentialsFlow", + g.NewQueryStruct("SetForOAuthClientCredentialsFlow"). + //OptionalQueryStructField("OAuthScopes", secretsIntegrationScopes, g.ParameterOptions().MustParentheses().SQL("OAUTH_SCOPES")), + ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses().Required()), + g.KeywordOptions(), + ). + OptionalQueryStructField( + "SetForOAuthAuthorizationFlow", + g.NewQueryStruct("SetForOAuthAuthorizationFlow"). + //optional or just TextAssignment()?? + OptionalTextAssignment("OAUTH_REFRESH_TOKEN", g.ParameterOptions().SingleQuotes()). + OptionalTextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().SingleQuotes()), + g.KeywordOptions(), + ). + OptionalQueryStructField( + "SetForBasicAuthentication", + g.NewQueryStruct("SetForBasicAuthentication"). + OptionalTextAssignment("USERNAME", g.ParameterOptions().SingleQuotes()). + OptionalTextAssignment("PASSWORD", g.ParameterOptions().SingleQuotes()), + g.KeywordOptions(), + ). + OptionalQueryStructField( + "SetForGenericString", + g.NewQueryStruct("SetForGenericString"). + OptionalTextAssignment("SECRET_STRING", g.ParameterOptions().SingleQuotes()), + g.KeywordOptions(), + ). + WithValidation(g.ExactlyOneValueSet, "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString") -// unset doest work, need to use "set comment = null" -// OptionalSQL("SET COMMENT = NULL") +// TODO: unset doest work, need to use "SET COMMENT = NULL" var secretUnset = g.NewQueryStruct("SecretUnset"). - OptionalSQL("UNSET COMMENT") + //OptionalSQL("UNSET COMMENT") + PredefinedQueryStructField("Comment", "*bool", g.KeywordOptions().SQL("SET COMMENT = NULL")) + +//OptionalSQL("SET COMMENT = NULL") var SecretsDef = g.NewInterface( "Secrets", @@ -39,8 +66,14 @@ var SecretsDef = g.NewInterface( Name(). PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION").Required()). - ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses()). - //QueryStructField("OAuthScopes", secretsOAuthScopes, g.ParameterOptions().MustParentheses()). + ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses().Required()). + /* + ListQueryStructField( + "OAuthScopes", + secretsSecurityIntegrationScopeDef, + g.KeywordOptions().Parentheses().SQL("OAUTH_SCOPES"), + ). + */ OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), @@ -106,7 +139,7 @@ var SecretsDef = g.NewInterface( OptionalQueryStructField( "Unset", secretUnset, - g.KeywordOptions().SQL("UNSET"), + g.KeywordOptions(), ). WithValidation(g.ExactlyOneValueSet, "Set", "Unset"), ) diff --git a/pkg/sdk/secrets_dto_builders_gen.go b/pkg/sdk/secrets_dto_builders_gen.go index dc1f083aa3..a8bacc259b 100644 --- a/pkg/sdk/secrets_dto_builders_gen.go +++ b/pkg/sdk/secrets_dto_builders_gen.go @@ -7,10 +7,12 @@ import () func NewCreateWithOAuthClientCredentialsFlowSecretRequest( name SchemaObjectIdentifier, SecurityIntegration AccountObjectIdentifier, + OauthScopes []SecurityIntegrationScope, ) *CreateWithOAuthClientCredentialsFlowSecretRequest { s := CreateWithOAuthClientCredentialsFlowSecretRequest{} s.name = name s.SecurityIntegration = SecurityIntegration + s.OauthScopes = OauthScopes return &s } @@ -24,11 +26,6 @@ func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithIfNotExists(IfNo return s } -func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithOauthScopes(OauthScopes []SecurityIntegrationScope) *CreateWithOAuthClientCredentialsFlowSecretRequest { - s.OauthScopes = OauthScopes - return s -} - func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithComment(Comment string) *CreateWithOAuthClientCredentialsFlowSecretRequest { s.Comment = &Comment return s @@ -147,42 +144,68 @@ func (s *SecretSetRequest) WithComment(Comment string) *SecretSetRequest { return s } -func (s *SecretSetRequest) WithOAuthScopes(OAuthScopes OAuthScopesRequest) *SecretSetRequest { - s.OAuthScopes = &OAuthScopes +func (s *SecretSetRequest) WithSetForOAuthClientCredentialsFlow(SetForOAuthClientCredentialsFlow SetForOAuthClientCredentialsFlowRequest) *SecretSetRequest { + s.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow + return s +} + +func (s *SecretSetRequest) WithSetForOAuthAuthorizationFlow(SetForOAuthAuthorizationFlow SetForOAuthAuthorizationFlowRequest) *SecretSetRequest { + s.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow + return s +} + +func (s *SecretSetRequest) WithSetForBasicAuthentication(SetForBasicAuthentication SetForBasicAuthenticationRequest) *SecretSetRequest { + s.SetForBasicAuthentication = &SetForBasicAuthentication + return s +} + +func (s *SecretSetRequest) WithSetForGenericString(SetForGenericString SetForGenericStringRequest) *SecretSetRequest { + s.SetForGenericString = &SetForGenericString return s } -func (s *SecretSetRequest) WithOauthRefreshToken(OauthRefreshToken string) *SecretSetRequest { +func NewSetForOAuthClientCredentialsFlowRequest( + OauthScopes []SecurityIntegrationScope, +) *SetForOAuthClientCredentialsFlowRequest { + s := SetForOAuthClientCredentialsFlowRequest{} + s.OauthScopes = OauthScopes + return &s +} + +func NewSetForOAuthAuthorizationFlowRequest() *SetForOAuthAuthorizationFlowRequest { + return &SetForOAuthAuthorizationFlowRequest{} +} + +func (s *SetForOAuthAuthorizationFlowRequest) WithOauthRefreshToken(OauthRefreshToken string) *SetForOAuthAuthorizationFlowRequest { s.OauthRefreshToken = &OauthRefreshToken return s } -func (s *SecretSetRequest) WithOauthRefreshTokenExpiryTime(OauthRefreshTokenExpiryTime string) *SecretSetRequest { +func (s *SetForOAuthAuthorizationFlowRequest) WithOauthRefreshTokenExpiryTime(OauthRefreshTokenExpiryTime string) *SetForOAuthAuthorizationFlowRequest { s.OauthRefreshTokenExpiryTime = &OauthRefreshTokenExpiryTime return s } -func (s *SecretSetRequest) WithUsername(Username string) *SecretSetRequest { - s.Username = &Username - return s +func NewSetForBasicAuthenticationRequest() *SetForBasicAuthenticationRequest { + return &SetForBasicAuthenticationRequest{} } -func (s *SecretSetRequest) WithPassword(Password string) *SecretSetRequest { - s.Password = &Password +func (s *SetForBasicAuthenticationRequest) WithUsername(Username string) *SetForBasicAuthenticationRequest { + s.Username = &Username return s } -func (s *SecretSetRequest) WithSecretString(SecretString string) *SecretSetRequest { - s.SecretString = &SecretString +func (s *SetForBasicAuthenticationRequest) WithPassword(Password string) *SetForBasicAuthenticationRequest { + s.Password = &Password return s } -func NewOAuthScopesRequest() *OAuthScopesRequest { - return &OAuthScopesRequest{} +func NewSetForGenericStringRequest() *SetForGenericStringRequest { + return &SetForGenericStringRequest{} } -func (s *OAuthScopesRequest) WithOAuthScopes(OAuthScopes []SecurityIntegrationScope) *OAuthScopesRequest { - s.OAuthScopes = OAuthScopes +func (s *SetForGenericStringRequest) WithSecretString(SecretString string) *SetForGenericStringRequest { + s.SecretString = &SecretString return s } @@ -190,7 +213,7 @@ func NewSecretUnsetRequest() *SecretUnsetRequest { return &SecretUnsetRequest{} } -func (s *SecretUnsetRequest) WithUnsetComment(UnsetComment bool) *SecretUnsetRequest { - s.UnsetComment = &UnsetComment +func (s *SecretUnsetRequest) WithComment(Comment bool) *SecretUnsetRequest { + s.Comment = &Comment return s } diff --git a/pkg/sdk/secrets_dto_gen.go b/pkg/sdk/secrets_dto_gen.go index 5f37d8caf0..5f23fd9a25 100644 --- a/pkg/sdk/secrets_dto_gen.go +++ b/pkg/sdk/secrets_dto_gen.go @@ -13,9 +13,9 @@ var ( type CreateWithOAuthClientCredentialsFlowSecretRequest struct { OrReplace *bool IfNotExists *bool - name SchemaObjectIdentifier // required - SecurityIntegration AccountObjectIdentifier // required - OauthScopes []SecurityIntegrationScope + name SchemaObjectIdentifier // required + SecurityIntegration AccountObjectIdentifier // required + OauthScopes []SecurityIntegrationScope // required Comment *string } @@ -54,19 +54,31 @@ type AlterSecretRequest struct { } type SecretSetRequest struct { - Comment *string - OAuthScopes *OAuthScopesRequest + Comment *string + SetForOAuthClientCredentialsFlow *SetForOAuthClientCredentialsFlowRequest + SetForOAuthAuthorizationFlow *SetForOAuthAuthorizationFlowRequest + SetForBasicAuthentication *SetForBasicAuthenticationRequest + SetForGenericString *SetForGenericStringRequest +} + +type SetForOAuthClientCredentialsFlowRequest struct { + OauthScopes []SecurityIntegrationScope // required +} + +type SetForOAuthAuthorizationFlowRequest struct { OauthRefreshToken *string OauthRefreshTokenExpiryTime *string - Username *string - Password *string - SecretString *string } -type OAuthScopesRequest struct { - OAuthScopes []SecurityIntegrationScope +type SetForBasicAuthenticationRequest struct { + Username *string + Password *string +} + +type SetForGenericStringRequest struct { + SecretString *string } type SecretUnsetRequest struct { - UnsetComment *bool + Comment *bool } diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index 9f5ac8638b..dd1f181069 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -72,20 +72,29 @@ type AlterSecretOptions struct { IfExists *bool `ddl:"keyword" sql:"IF EXISTS"` name SchemaObjectIdentifier `ddl:"identifier"` Set *SecretSet `ddl:"keyword" sql:"SET"` - Unset *SecretUnset `ddl:"keyword" sql:"UNSET"` + Unset *SecretUnset `ddl:"keyword"` } type SecretSet struct { - Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` - OAuthScopes *OAuthScopes `ddl:"parameter,must_parentheses" sql:"OAUTH_SCOPES"` - OauthRefreshToken *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` - OauthRefreshTokenExpiryTime *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN_EXPIRY_TIME"` - Username *string `ddl:"parameter,single_quotes" sql:"USERNAME"` - Password *string `ddl:"parameter,single_quotes" sql:"PASSWORD"` - SecretString *string `ddl:"parameter,single_quotes" sql:"SECRET_STRING"` + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` + SetForOAuthClientCredentialsFlow *SetForOAuthClientCredentialsFlow `ddl:"keyword"` + SetForOAuthAuthorizationFlow *SetForOAuthAuthorizationFlow `ddl:"keyword"` + SetForBasicAuthentication *SetForBasicAuthentication `ddl:"keyword"` + SetForGenericString *SetForGenericString `ddl:"keyword"` } -type OAuthScopes struct { - OAuthScopes []SecurityIntegrationScope `ddl:"list,must_parentheses"` +type SetForOAuthClientCredentialsFlow struct { + OauthScopes []SecurityIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` +} +type SetForOAuthAuthorizationFlow struct { + OauthRefreshToken *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` + OauthRefreshTokenExpiryTime *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN_EXPIRY_TIME"` +} +type SetForBasicAuthentication struct { + Username *string `ddl:"parameter,single_quotes" sql:"USERNAME"` + Password *string `ddl:"parameter,single_quotes" sql:"PASSWORD"` +} +type SetForGenericString struct { + SecretString *string `ddl:"parameter,single_quotes" sql:"SECRET_STRING"` } type SecretUnset struct { - UnsetComment *bool `ddl:"keyword" sql:"UNSET COMMENT"` + Comment *bool `ddl:"keyword" sql:"SET COMMENT = NULL"` } diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 426e5eee09..bac04d5e29 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -30,14 +30,9 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { }) t.Run("basic", func(t *testing.T) { - securityIntegration := NewAccountObjectIdentifier("security_integration") - oauthScopes := []SecurityIntegrationScope{{Scope: "sample_scope"}} - opts := defaultOpts() - opts.SecurityIntegration = securityIntegration - opts.OauthScopes = oauthScopes // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName(), securityIntegration.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) t.Run("all options", func(t *testing.T) { @@ -168,48 +163,84 @@ func TestSecrets_CreateWithGenericString(t *testing.T) { } func TestSecrets_Alter(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid AlterSecretOptions + defaultOpts := func() *AlterSecretOptions { return &AlterSecretOptions{ - name: id, } } + setOpts := func() *AlterSecretOptions { + return &AlterSecretOptions{ + name: id, + Set: &SecretSet{}, + IfExists: Bool(true), + } + } + + unsetOpts := func() *AlterSecretOptions { + return &AlterSecretOptions{ + name: id, + Unset: &SecretUnset{}, + IfExists: Bool(true), + } + } + t.Run("validation: nil options", func(t *testing.T) { var opts *AlterSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) + t.Run("validation: exactly one field from [opts.Set opts.Unset] should be present", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) }) - t.Run("alter: set options", func(t *testing.T) { - oauthScopes := &OAuthScopes{[]SecurityIntegrationScope{{Scope: "different_scope_name"}}} + t.Run("validation: exactly one field from [opts.Set.SetForOAuthClientCredentialsFlow opts.Set.SetForOAuthAuthorizationFlow opts.Set.SetForBasicAuthentication opts.Set.SetForGenericString] should be present", func(t *testing.T) { + opts := setOpts() + opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{} + opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{} + assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + }) - opts := defaultOpts() - opts.Set = &SecretSet{ - OAuthScopes: oauthScopes, - OauthRefreshToken: String("refresh_token"), - OauthRefreshTokenExpiryTime: String("2024-10-10"), + t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{[]SecurityIntegrationScope{{"sample_scope"}}} + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName()) + }) + + t.Run("alter: set options for Oauth Authorization Flow", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ + String("test_token"), + String("2024-11-11"), } - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET %s SET OAUTH_SCOPES = ('different_scope_name')", id.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_REFRESH_TOKEN = 'test_token' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2024-11-11'", id.FullyQualifiedName()) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + t.Run("alter: set options for Basic Authentication", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{ + Username: String("foo"), + Password: String("bar"), + } + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' USERNAME = 'foo' PASSWORD = 'bar'", id.FullyQualifiedName()) }) - t.Run("all options", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + t.Run("alter: set options for Generic string", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForGenericString = &SetForGenericString{String("test")} + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' SECRET_STRING = 'test'", id.FullyQualifiedName()) + }) + + t.Run("alter: unset options", func(t *testing.T) { + opts := unsetOpts() + opts.Unset.Comment = Bool(true) + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = NULL", id.FullyQualifiedName()) }) } diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index bdce5ad21a..a5995fe3ce 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -90,19 +90,41 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { } if r.Set != nil { + opts.Set = &SecretSet{ Comment: r.Set.Comment, + } + + if r.Set.SetForOAuthClientCredentialsFlow != nil { + + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{ + OauthScopes: r.Set.SetForOAuthClientCredentialsFlow.OauthScopes, + } - OauthRefreshToken: r.Set.OauthRefreshToken, - OauthRefreshTokenExpiryTime: r.Set.OauthRefreshTokenExpiryTime, - Username: r.Set.Username, - Password: r.Set.Password, - SecretString: r.Set.SecretString, } - if r.Set.OAuthScopes != nil { - opts.Set.OAuthScopes = &OAuthScopes{ - OAuthScopes: r.Set.OAuthScopes.OAuthScopes, + if r.Set.SetForOAuthAuthorizationFlow != nil { + + opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ + OauthRefreshToken: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshToken, + OauthRefreshTokenExpiryTime: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshTokenExpiryTime, + } + + } + + if r.Set.SetForBasicAuthentication != nil { + + opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{ + Username: r.Set.SetForBasicAuthentication.Username, + Password: r.Set.SetForBasicAuthentication.Password, + } + + } + + if r.Set.SetForGenericString != nil { + + opts.Set.SetForGenericString = &SetForGenericString{ + SecretString: r.Set.SetForGenericString.SecretString, } } @@ -110,8 +132,9 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { } if r.Unset != nil { + opts.Unset = &SecretUnset{ - UnsetComment: r.Unset.UnsetComment, + Comment: r.Unset.Comment, } } diff --git a/pkg/sdk/secrets_validations_gen.go b/pkg/sdk/secrets_validations_gen.go index 513145bf1c..e703dbec57 100644 --- a/pkg/sdk/secrets_validations_gen.go +++ b/pkg/sdk/secrets_validations_gen.go @@ -72,5 +72,10 @@ func (opts *AlterSecretOptions) validate() error { if !exactlyOneValueSet(opts.Set, opts.Unset) { errs = append(errs, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) } + if valueSet(opts.Set) { + if !exactlyOneValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { + errs = append(errs, errExactlyOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + } + } return JoinErrors(errs...) } From 57ca19a26af904a0a40962512f6425f875450af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Fri, 13 Sep 2024 15:30:59 +0200 Subject: [PATCH 05/34] add tests for all four create types --- pkg/sdk/secrets_gen_test.go | 99 ++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 56 deletions(-) diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index bac04d5e29..89f7de7966 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -3,12 +3,10 @@ package sdk import "testing" func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithOAuthClientCredentialsFlowSecretOptions + defaultOpts := func() *CreateWithOAuthClientCredentialsFlowSecretOptions { return &CreateWithOAuthClientCredentialsFlowSecretOptions{ - name: id, } } @@ -17,38 +15,36 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { var opts *CreateWithOAuthClientCredentialsFlowSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthClientCredentialsFlowSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { + integration := randomAccountObjectIdentifier() + opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.SecurityIntegration = integration + opts.OauthScopes = []SecurityIntegrationScope{{"test"}} + opts.Comment = String("foo") + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('test') COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) } func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithOAuthAuthorizationCodeFlowSecretOptions + defaultOpts := func() *CreateWithOAuthAuthorizationCodeFlowSecretOptions { return &CreateWithOAuthAuthorizationCodeFlowSecretOptions{ - name: id, } } @@ -57,38 +53,37 @@ func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { var opts *CreateWithOAuthAuthorizationCodeFlowSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthAuthorizationCodeFlowSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { + integration := randomAccountObjectIdentifier() + opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.OauthRefreshToken = "foo" + opts.OauthRefreshTokenExpiryTime = "bar" + opts.SecurityIntegration = integration + opts.Comment = String("test") + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 OAUTH_REFRESH_TOKEN = 'foo' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = 'bar' API_AUTHENTICATION = %s COMMENT = 'test'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) } func TestSecrets_CreateWithBasicAuthentication(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithBasicAuthenticationSecretOptions + defaultOpts := func() *CreateWithBasicAuthenticationSecretOptions { return &CreateWithBasicAuthenticationSecretOptions{ - name: id, } } @@ -97,38 +92,34 @@ func TestSecrets_CreateWithBasicAuthentication(t *testing.T) { var opts *CreateWithBasicAuthenticationSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithBasicAuthenticationSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.Username = "foo" + opts.Password = "bar" + opts.Comment = String("test") + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = PASSWORD USERNAME = 'foo' PASSWORD = 'bar' COMMENT = 'test'", id.FullyQualifiedName()) }) } func TestSecrets_CreateWithGenericString(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithGenericStringSecretOptions + defaultOpts := func() *CreateWithGenericStringSecretOptions { return &CreateWithGenericStringSecretOptions{ - name: id, } } @@ -137,28 +128,24 @@ func TestSecrets_CreateWithGenericString(t *testing.T) { var opts *CreateWithGenericStringSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithGenericStringSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.SecretString = "test" + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = GENERIC_STRING SECRET_STRING = 'test'", id.FullyQualifiedName()) }) } From 8d55a63c9aaa23a0d784c7009c78caabd5e53f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 16 Sep 2024 11:24:34 +0200 Subject: [PATCH 06/34] rename previous secret to secretReference in common_types.go due to naming clash --- pkg/sdk/common_types.go | 2 +- pkg/sdk/functions_def.go | 4 ++-- pkg/sdk/functions_dto_builders_gen.go | 4 ++-- pkg/sdk/functions_dto_gen.go | 4 ++-- pkg/sdk/functions_gen.go | 4 ++-- pkg/sdk/functions_gen_test.go | 4 ++-- pkg/sdk/procedures_def.go | 4 ++-- pkg/sdk/procedures_dto_builders_gen.go | 4 ++-- pkg/sdk/procedures_dto_gen.go | 4 ++-- pkg/sdk/procedures_gen.go | 4 ++-- pkg/sdk/procedures_gen_test.go | 4 ++-- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pkg/sdk/common_types.go b/pkg/sdk/common_types.go index f99fe2fdd5..1627ab9d2a 100644 --- a/pkg/sdk/common_types.go +++ b/pkg/sdk/common_types.go @@ -257,7 +257,7 @@ func ReturnNullValuesPointer(v ReturnNullValues) *ReturnNullValues { return &v } -type Secret struct { +type SecretReference struct { VariableName string `ddl:"keyword,single_quotes"` Name string `ddl:"parameter,no_quotes"` } diff --git a/pkg/sdk/functions_def.go b/pkg/sdk/functions_def.go index 4411f6a389..017ccd8335 100644 --- a/pkg/sdk/functions_def.go +++ b/pkg/sdk/functions_def.go @@ -79,7 +79,7 @@ var FunctionsDef = g.NewInterface( ). TextAssignment("HANDLER", g.ParameterOptions().SingleQuotes().Required()). ListAssignment("EXTERNAL_ACCESS_INTEGRATIONS", "AccountObjectIdentifier", g.ParameterOptions().Parentheses()). - ListAssignment("SECRETS", "Secret", g.ParameterOptions().Parentheses()). + ListAssignment("SECRETS", "SecretReference", g.ParameterOptions().Parentheses()). OptionalTextAssignment("TARGET_PATH", g.ParameterOptions().SingleQuotes()). PredefinedQueryStructField("FunctionDefinition", "*string", g.ParameterOptions().NoEquals().SingleQuotes().SQL("AS")). WithValidation(g.ValidIdentifier, "name"). @@ -152,7 +152,7 @@ var FunctionsDef = g.NewInterface( ). TextAssignment("HANDLER", g.ParameterOptions().SingleQuotes().Required()). ListAssignment("EXTERNAL_ACCESS_INTEGRATIONS", "AccountObjectIdentifier", g.ParameterOptions().Parentheses()). - ListAssignment("SECRETS", "Secret", g.ParameterOptions().Parentheses()). + ListAssignment("SECRETS", "SecretReference", g.ParameterOptions().Parentheses()). PredefinedQueryStructField("FunctionDefinition", "*string", g.ParameterOptions().NoEquals().SingleQuotes().SQL("AS")). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ValidateValueSet, "RuntimeVersion"). diff --git a/pkg/sdk/functions_dto_builders_gen.go b/pkg/sdk/functions_dto_builders_gen.go index 0a72ce0fdc..0aef014932 100644 --- a/pkg/sdk/functions_dto_builders_gen.go +++ b/pkg/sdk/functions_dto_builders_gen.go @@ -86,7 +86,7 @@ func (s *CreateForJavaFunctionRequest) WithExternalAccessIntegrations(ExternalAc return s } -func (s *CreateForJavaFunctionRequest) WithSecrets(Secrets []Secret) *CreateForJavaFunctionRequest { +func (s *CreateForJavaFunctionRequest) WithSecrets(Secrets []SecretReference) *CreateForJavaFunctionRequest { s.Secrets = Secrets return s } @@ -311,7 +311,7 @@ func (s *CreateForPythonFunctionRequest) WithExternalAccessIntegrations(External return s } -func (s *CreateForPythonFunctionRequest) WithSecrets(Secrets []Secret) *CreateForPythonFunctionRequest { +func (s *CreateForPythonFunctionRequest) WithSecrets(Secrets []SecretReference) *CreateForPythonFunctionRequest { s.Secrets = Secrets return s } diff --git a/pkg/sdk/functions_dto_gen.go b/pkg/sdk/functions_dto_gen.go index 6376eea28b..3fa0ff387b 100644 --- a/pkg/sdk/functions_dto_gen.go +++ b/pkg/sdk/functions_dto_gen.go @@ -32,7 +32,7 @@ type CreateForJavaFunctionRequest struct { Packages []FunctionPackageRequest Handler string // required ExternalAccessIntegrations []AccountObjectIdentifier - Secrets []Secret + Secrets []SecretReference TargetPath *string FunctionDefinition *string } @@ -102,7 +102,7 @@ type CreateForPythonFunctionRequest struct { Packages []FunctionPackageRequest Handler string // required ExternalAccessIntegrations []AccountObjectIdentifier - Secrets []Secret + Secrets []SecretReference FunctionDefinition *string } diff --git a/pkg/sdk/functions_gen.go b/pkg/sdk/functions_gen.go index 7c3d55d76b..85f2b8378d 100644 --- a/pkg/sdk/functions_gen.go +++ b/pkg/sdk/functions_gen.go @@ -40,7 +40,7 @@ type CreateForJavaFunctionOptions struct { Packages []FunctionPackage `ddl:"parameter,parentheses" sql:"PACKAGES"` Handler string `ddl:"parameter,single_quotes" sql:"HANDLER"` ExternalAccessIntegrations []AccountObjectIdentifier `ddl:"parameter,parentheses" sql:"EXTERNAL_ACCESS_INTEGRATIONS"` - Secrets []Secret `ddl:"parameter,parentheses" sql:"SECRETS"` + Secrets []SecretReference `ddl:"parameter,parentheses" sql:"SECRETS"` TargetPath *string `ddl:"parameter,single_quotes" sql:"TARGET_PATH"` FunctionDefinition *string `ddl:"parameter,single_quotes,no_equals" sql:"AS"` } @@ -118,7 +118,7 @@ type CreateForPythonFunctionOptions struct { Packages []FunctionPackage `ddl:"parameter,parentheses" sql:"PACKAGES"` Handler string `ddl:"parameter,single_quotes" sql:"HANDLER"` ExternalAccessIntegrations []AccountObjectIdentifier `ddl:"parameter,parentheses" sql:"EXTERNAL_ACCESS_INTEGRATIONS"` - Secrets []Secret `ddl:"parameter,parentheses" sql:"SECRETS"` + Secrets []SecretReference `ddl:"parameter,parentheses" sql:"SECRETS"` FunctionDefinition *string `ddl:"parameter,single_quotes,no_equals" sql:"AS"` } diff --git a/pkg/sdk/functions_gen_test.go b/pkg/sdk/functions_gen_test.go index 0bb4778832..b0c1c5b0b5 100644 --- a/pkg/sdk/functions_gen_test.go +++ b/pkg/sdk/functions_gen_test.go @@ -103,7 +103,7 @@ func TestFunctions_CreateForJava(t *testing.T) { opts.ExternalAccessIntegrations = []AccountObjectIdentifier{ NewAccountObjectIdentifier("ext_integration"), } - opts.Secrets = []Secret{ + opts.Secrets = []SecretReference{ { VariableName: "variable1", Name: "name1", @@ -272,7 +272,7 @@ func TestFunctions_CreateForPython(t *testing.T) { opts.ExternalAccessIntegrations = []AccountObjectIdentifier{ NewAccountObjectIdentifier("ext_integration"), } - opts.Secrets = []Secret{ + opts.Secrets = []SecretReference{ { VariableName: "variable1", Name: "name1", diff --git a/pkg/sdk/procedures_def.go b/pkg/sdk/procedures_def.go index 1788c99a44..3b5eb69882 100644 --- a/pkg/sdk/procedures_def.go +++ b/pkg/sdk/procedures_def.go @@ -101,7 +101,7 @@ var ProceduresDef = g.NewInterface( ). TextAssignment("HANDLER", g.ParameterOptions().SingleQuotes().Required()). ListAssignment("EXTERNAL_ACCESS_INTEGRATIONS", "AccountObjectIdentifier", g.ParameterOptions().Parentheses()). - ListAssignment("SECRETS", "Secret", g.ParameterOptions().Parentheses()). + ListAssignment("SECRETS", "SecretReference", g.ParameterOptions().Parentheses()). OptionalTextAssignment("TARGET_PATH", g.ParameterOptions().SingleQuotes()). PredefinedQueryStructField("NullInputBehavior", "*NullInputBehavior", g.KeywordOptions()). OptionalTextAssignment("COMMENT", g.ParameterOptions().SingleQuotes()). @@ -169,7 +169,7 @@ var ProceduresDef = g.NewInterface( ). TextAssignment("HANDLER", g.ParameterOptions().SingleQuotes().Required()). ListAssignment("EXTERNAL_ACCESS_INTEGRATIONS", "AccountObjectIdentifier", g.ParameterOptions().Parentheses()). - ListAssignment("SECRETS", "Secret", g.ParameterOptions().Parentheses()). + ListAssignment("SECRETS", "SecretReference", g.ParameterOptions().Parentheses()). PredefinedQueryStructField("NullInputBehavior", "*NullInputBehavior", g.KeywordOptions()). OptionalTextAssignment("COMMENT", g.ParameterOptions().SingleQuotes()). PredefinedQueryStructField("ExecuteAs", "*ExecuteAs", g.KeywordOptions()). diff --git a/pkg/sdk/procedures_dto_builders_gen.go b/pkg/sdk/procedures_dto_builders_gen.go index 75671ecf4e..c88c8bd9ac 100644 --- a/pkg/sdk/procedures_dto_builders_gen.go +++ b/pkg/sdk/procedures_dto_builders_gen.go @@ -50,7 +50,7 @@ func (s *CreateForJavaProcedureRequest) WithExternalAccessIntegrations(ExternalA return s } -func (s *CreateForJavaProcedureRequest) WithSecrets(Secrets []Secret) *CreateForJavaProcedureRequest { +func (s *CreateForJavaProcedureRequest) WithSecrets(Secrets []SecretReference) *CreateForJavaProcedureRequest { s.Secrets = Secrets return s } @@ -260,7 +260,7 @@ func (s *CreateForPythonProcedureRequest) WithExternalAccessIntegrations(Externa return s } -func (s *CreateForPythonProcedureRequest) WithSecrets(Secrets []Secret) *CreateForPythonProcedureRequest { +func (s *CreateForPythonProcedureRequest) WithSecrets(Secrets []SecretReference) *CreateForPythonProcedureRequest { s.Secrets = Secrets return s } diff --git a/pkg/sdk/procedures_dto_gen.go b/pkg/sdk/procedures_dto_gen.go index 398169a682..8ad24b86e6 100644 --- a/pkg/sdk/procedures_dto_gen.go +++ b/pkg/sdk/procedures_dto_gen.go @@ -32,7 +32,7 @@ type CreateForJavaProcedureRequest struct { Imports []ProcedureImportRequest Handler string // required ExternalAccessIntegrations []AccountObjectIdentifier - Secrets []Secret + Secrets []SecretReference TargetPath *string NullInputBehavior *NullInputBehavior Comment *string @@ -100,7 +100,7 @@ type CreateForPythonProcedureRequest struct { Imports []ProcedureImportRequest Handler string // required ExternalAccessIntegrations []AccountObjectIdentifier - Secrets []Secret + Secrets []SecretReference NullInputBehavior *NullInputBehavior Comment *string ExecuteAs *ExecuteAs diff --git a/pkg/sdk/procedures_gen.go b/pkg/sdk/procedures_gen.go index b12fd6beeb..e265558f70 100644 --- a/pkg/sdk/procedures_gen.go +++ b/pkg/sdk/procedures_gen.go @@ -40,7 +40,7 @@ type CreateForJavaProcedureOptions struct { Imports []ProcedureImport `ddl:"parameter,parentheses" sql:"IMPORTS"` Handler string `ddl:"parameter,single_quotes" sql:"HANDLER"` ExternalAccessIntegrations []AccountObjectIdentifier `ddl:"parameter,parentheses" sql:"EXTERNAL_ACCESS_INTEGRATIONS"` - Secrets []Secret `ddl:"parameter,parentheses" sql:"SECRETS"` + Secrets []SecretReference `ddl:"parameter,parentheses" sql:"SECRETS"` TargetPath *string `ddl:"parameter,single_quotes" sql:"TARGET_PATH"` NullInputBehavior *NullInputBehavior `ddl:"keyword"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` @@ -116,7 +116,7 @@ type CreateForPythonProcedureOptions struct { Imports []ProcedureImport `ddl:"parameter,parentheses" sql:"IMPORTS"` Handler string `ddl:"parameter,single_quotes" sql:"HANDLER"` ExternalAccessIntegrations []AccountObjectIdentifier `ddl:"parameter,parentheses" sql:"EXTERNAL_ACCESS_INTEGRATIONS"` - Secrets []Secret `ddl:"parameter,parentheses" sql:"SECRETS"` + Secrets []SecretReference `ddl:"parameter,parentheses" sql:"SECRETS"` NullInputBehavior *NullInputBehavior `ddl:"keyword"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` ExecuteAs *ExecuteAs `ddl:"keyword"` diff --git a/pkg/sdk/procedures_gen_test.go b/pkg/sdk/procedures_gen_test.go index 6345324d0b..7717308d51 100644 --- a/pkg/sdk/procedures_gen_test.go +++ b/pkg/sdk/procedures_gen_test.go @@ -93,7 +93,7 @@ func TestProcedures_CreateForJava(t *testing.T) { opts.ExternalAccessIntegrations = []AccountObjectIdentifier{ NewAccountObjectIdentifier("ext_integration"), } - opts.Secrets = []Secret{ + opts.Secrets = []SecretReference{ { VariableName: "variable1", Name: "name1", @@ -235,7 +235,7 @@ func TestProcedures_CreateForPython(t *testing.T) { opts.ExternalAccessIntegrations = []AccountObjectIdentifier{ NewAccountObjectIdentifier("ext_integration"), } - opts.Secrets = []Secret{ + opts.Secrets = []SecretReference{ { VariableName: "variable1", Name: "name1", From 9894799b9b81b016a4675c1fe68d103607d34af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 16 Sep 2024 11:25:02 +0200 Subject: [PATCH 07/34] secrets gen with drop, show and desc --- pkg/sdk/secrets_def.go | 93 +++++++++++++++++++++---- pkg/sdk/secrets_dto_builders_gen.go | 35 ++++++++++ pkg/sdk/secrets_dto_gen.go | 17 +++++ pkg/sdk/secrets_gen.go | 82 +++++++++++++++++++++- pkg/sdk/secrets_gen_integration_test.go | 16 +++++ pkg/sdk/secrets_gen_test.go | 89 +++++++++++++++++++++++ pkg/sdk/secrets_impl_gen.go | 70 +++++++++++++++++++ pkg/sdk/secrets_validations_gen.go | 33 +++++++++ 8 files changed, 420 insertions(+), 15 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 204db83165..9d3ae947c9 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -7,10 +7,56 @@ import g "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/gen var secretsSecurityIntegrationScopeDef = g.NewQueryStruct("SecurityIntegrationScope"). Text("Scope", g.KeywordOptions().SingleQuotes().Required()) -/* -var secretsIntegrationScopes = g.NewQueryStruct("OAuthScopes"). - List("OAuthScopes", "SecurityIntegrationScope", g.ListOptions().MustParentheses()) -*/ +var secretDbRow = g.DbStruct("secretDBRow"). + Field("created_on", "string"). + Field("name", "string"). + Field("schema_name", "string"). + Field("database_name", "string"). + Field("owner", "string"). + Field("comment", "sql.NullString"). + Field("secret_type", "string"). + Field("oauth_scopes", "sql.NullString"). // its a list tho + Field("owner_role_type", "string") + +// cannot name 'secret' due to clash in common_types.go +var secret = g.PlainStruct("Secret"). + Field("CreatedOn", "string"). + Field("Name", "string"). + Field("SchemaName", "string"). + Field("DatabaseName", "string"). + Field("Owner", "string"). + Field("Comment", "string"). + Field("SecretType", "string"). + Field("OauthScopes", "sql.NullString"). + Field("OwnerRoleType", "string") + +var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). + Field("created_on", "string"). + Field("name", "string"). + Field("schema_name", "string"). + Field("database_name", "string"). + Field("owner", "string"). + Field("comment", "sql.NullString"). + Field("secret_type", "string"). + Field("username", "sql.NullString"). + Field("oauth_access_token_expiry_time", "sql.NullString"). + Field("oauth_refresh_token_expiry_time", "sql.NullString"). + Field("oauth_scopes", "sql.NullString"). // its a list tho + Field("integration_name", "sql.NullString") + +var secretDetails = g.PlainStruct("SecretDetails"). + Field("CreatedOn", "string"). + Field("Name", "string"). + Field("SchemaName", "string"). + Field("DatabaseName", "string"). + Field("Owner", "string"). + Field("Comment", "sql.NullString"). + Field("SecretType", "string"). + Field("Username", "sql.NullString"). + Field("OauthAccessTokenExpiryTime", "sql.NullString"). + Field("OauthRefreshTokenExpiryTime", "sql.NullString"). + Field("OauthScopes", "sql.NullString"). // its a list tho + Field("IntegrationName", "sql.NullString") var secretSet = g.NewQueryStruct("SecretSet"). OptionalComment(). @@ -49,8 +95,6 @@ var secretUnset = g.NewQueryStruct("SecretUnset"). //OptionalSQL("UNSET COMMENT") PredefinedQueryStructField("Comment", "*bool", g.KeywordOptions().SQL("SET COMMENT = NULL")) -//OptionalSQL("SET COMMENT = NULL") - var SecretsDef = g.NewInterface( "Secrets", "Secret", @@ -67,13 +111,6 @@ var SecretsDef = g.NewInterface( PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION").Required()). ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses().Required()). - /* - ListQueryStructField( - "OAuthScopes", - secretsSecurityIntegrationScopeDef, - g.KeywordOptions().Parentheses().SQL("OAUTH_SCOPES"), - ). - */ OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), @@ -142,4 +179,32 @@ var SecretsDef = g.NewInterface( g.KeywordOptions(), ). WithValidation(g.ExactlyOneValueSet, "Set", "Unset"), -) +).DropOperation( + "https://docs.snowflake.com/en/sql-reference/sql/drop-secret", + g.NewQueryStruct("DropSecret"). + Drop(). + SQL("SECRET"). + IfExists(). + Name(). + WithValidation(g.ValidIdentifier, "name"), +).ShowOperation( + "https://docs.snowflake.com/en/sql-reference/sql/show-secret", + secretDbRow, + secret, + g.NewQueryStruct("ShowSecret"). + Show(). + SQL("SECRETS"). + OptionalLike(). + OptionalIn(), +).ShowByIdOperation(). + DescribeOperation( + g.DescriptionMappingKindSingleValue, + "https://docs.snowflake.com/en/sql-reference/sql/desc-secret", + secretDetailsDbRow, + secretDetails, + g.NewQueryStruct("DescribeSecret"). + Describe(). + SQL("SECRET"). + Name(). + WithValidation(g.ValidIdentifier, "name"), + ) diff --git a/pkg/sdk/secrets_dto_builders_gen.go b/pkg/sdk/secrets_dto_builders_gen.go index a8bacc259b..faf3a01bf9 100644 --- a/pkg/sdk/secrets_dto_builders_gen.go +++ b/pkg/sdk/secrets_dto_builders_gen.go @@ -217,3 +217,38 @@ func (s *SecretUnsetRequest) WithComment(Comment bool) *SecretUnsetRequest { s.Comment = &Comment return s } + +func NewDropSecretRequest( + name SchemaObjectIdentifier, +) *DropSecretRequest { + s := DropSecretRequest{} + s.name = name + return &s +} + +func (s *DropSecretRequest) WithIfExists(IfExists bool) *DropSecretRequest { + s.IfExists = &IfExists + return s +} + +func NewShowSecretRequest() *ShowSecretRequest { + return &ShowSecretRequest{} +} + +func (s *ShowSecretRequest) WithLike(Like Like) *ShowSecretRequest { + s.Like = &Like + return s +} + +func (s *ShowSecretRequest) WithIn(In In) *ShowSecretRequest { + s.In = &In + return s +} + +func NewDescribeSecretRequest( + name SchemaObjectIdentifier, +) *DescribeSecretRequest { + s := DescribeSecretRequest{} + s.name = name + return &s +} diff --git a/pkg/sdk/secrets_dto_gen.go b/pkg/sdk/secrets_dto_gen.go index 5f23fd9a25..36d3f1ef22 100644 --- a/pkg/sdk/secrets_dto_gen.go +++ b/pkg/sdk/secrets_dto_gen.go @@ -8,6 +8,9 @@ var ( _ optionsProvider[CreateWithBasicAuthenticationSecretOptions] = new(CreateWithBasicAuthenticationSecretRequest) _ optionsProvider[CreateWithGenericStringSecretOptions] = new(CreateWithGenericStringSecretRequest) _ optionsProvider[AlterSecretOptions] = new(AlterSecretRequest) + _ optionsProvider[DropSecretOptions] = new(DropSecretRequest) + _ optionsProvider[ShowSecretOptions] = new(ShowSecretRequest) + _ optionsProvider[DescribeSecretOptions] = new(DescribeSecretRequest) ) type CreateWithOAuthClientCredentialsFlowSecretRequest struct { @@ -82,3 +85,17 @@ type SetForGenericStringRequest struct { type SecretUnsetRequest struct { Comment *bool } + +type DropSecretRequest struct { + IfExists *bool + name SchemaObjectIdentifier // required +} + +type ShowSecretRequest struct { + Like *Like + In *In +} + +type DescribeSecretRequest struct { + name SchemaObjectIdentifier // required +} diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index dd1f181069..6ff0313c1e 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -1,6 +1,9 @@ package sdk -import "context" +import ( + "context" + "database/sql" +) type Secrets interface { CreateWithOAuthClientCredentialsFlow(ctx context.Context, request *CreateWithOAuthClientCredentialsFlowSecretRequest) error @@ -8,6 +11,10 @@ type Secrets interface { CreateWithBasicAuthentication(ctx context.Context, request *CreateWithBasicAuthenticationSecretRequest) error CreateWithGenericString(ctx context.Context, request *CreateWithGenericStringSecretRequest) error Alter(ctx context.Context, request *AlterSecretRequest) error + Drop(ctx context.Context, request *DropSecretRequest) error + Show(ctx context.Context, request *ShowSecretRequest) ([]Secret, error) + ShowByID(ctx context.Context, id SchemaObjectIdentifier) (*Secret, error) + Describe(ctx context.Context, id SchemaObjectIdentifier) (*SecretDetails, error) } // CreateWithOAuthClientCredentialsFlowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-secret. @@ -98,3 +105,76 @@ type SetForGenericString struct { type SecretUnset struct { Comment *bool `ddl:"keyword" sql:"SET COMMENT = NULL"` } + +// DropSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/drop-secret. +type DropSecretOptions struct { + drop bool `ddl:"static" sql:"DROP"` + secret bool `ddl:"static" sql:"SECRET"` + IfExists *bool `ddl:"keyword" sql:"IF EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` +} + +// ShowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/show-secret. +type ShowSecretOptions struct { + show bool `ddl:"static" sql:"SHOW"` + secrets bool `ddl:"static" sql:"SECRETS"` + Like *Like `ddl:"keyword" sql:"LIKE"` + In *In `ddl:"keyword" sql:"IN"` +} +type secretDBRow struct { + CreatedOn string `db:"created_on"` + Name string `db:"name"` + SchemaName string `db:"schema_name"` + DatabaseName string `db:"database_name"` + Owner string `db:"owner"` + Comment sql.NullString `db:"comment"` + SecretType string `db:"secret_type"` + OauthScopes sql.NullString `db:"oauth_scopes"` + OwnerRoleType string `db:"owner_role_type"` +} +type Secret struct { + CreatedOn string + Name string + SchemaName string + DatabaseName string + Owner string + Comment string + SecretType string + OauthScopes sql.NullString + OwnerRoleType string +} + +// DescribeSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/desc-secret. +type DescribeSecretOptions struct { + describe bool `ddl:"static" sql:"DESCRIBE"` + secret bool `ddl:"static" sql:"SECRET"` + name SchemaObjectIdentifier `ddl:"identifier"` +} +type secretDetailsDBRow struct { + CreatedOn string `db:"created_on"` + Name string `db:"name"` + SchemaName string `db:"schema_name"` + DatabaseName string `db:"database_name"` + Owner string `db:"owner"` + Comment sql.NullString `db:"comment"` + SecretType string `db:"secret_type"` + Username sql.NullString `db:"username"` + OauthAccessTokenExpiryTime sql.NullString `db:"oauth_access_token_expiry_time"` + OauthRefreshTokenExpiryTime sql.NullString `db:"oauth_refresh_token_expiry_time"` + OauthScopes sql.NullString `db:"oauth_scopes"` + IntegrationName sql.NullString `db:"integration_name"` +} +type SecretDetails struct { + CreatedOn string + Name string + SchemaName string + DatabaseName string + Owner string + Comment sql.NullString + SecretType string + Username sql.NullString + OauthAccessTokenExpiryTime sql.NullString + OauthRefreshTokenExpiryTime sql.NullString + OauthScopes sql.NullString + IntegrationName sql.NullString +} diff --git a/pkg/sdk/secrets_gen_integration_test.go b/pkg/sdk/secrets_gen_integration_test.go index ee9af4239a..4474555b36 100644 --- a/pkg/sdk/secrets_gen_integration_test.go +++ b/pkg/sdk/secrets_gen_integration_test.go @@ -24,4 +24,20 @@ func TestInt_Secrets(t *testing.T) { t.Run("Alter", func(t *testing.T) { // TODO: fill me }) + + t.Run("Drop", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Show", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("ShowByID", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Describe", func(t *testing.T) { + // TODO: fill me + }) } diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 89f7de7966..a07505fdb8 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -231,3 +231,92 @@ func TestSecrets_Alter(t *testing.T) { assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = NULL", id.FullyQualifiedName()) }) } + +func TestSecrets_Drop(t *testing.T) { + id := randomSchemaObjectIdentifier() + defaultOpts := func() *DropSecretOptions { + return &DropSecretOptions{ + name: id, + } + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *DropSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + opts := defaultOpts() + opts.name = emptySchemaObjectIdentifier + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} + +func TestSecrets_Show(t *testing.T) { + // Minimal valid ShowSecretOptions + defaultOpts := func() *ShowSecretOptions { + return &ShowSecretOptions{} + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *ShowSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} + +func TestSecrets_Describe(t *testing.T) { + + id := randomSchemaObjectIdentifier() + // Minimal valid DescribeSecretOptions + defaultOpts := func() *DescribeSecretOptions { + return &DescribeSecretOptions{ + + name: id, + } + } + + t.Run("validation: nil options", func(t *testing.T) { + var opts *DescribeSecretOptions = nil + assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) + }) + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) + }) + + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) +} diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index a5995fe3ce..dc31263fc8 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -2,6 +2,8 @@ package sdk import ( "context" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/collections" ) var _ Secrets = (*secrets)(nil) @@ -35,6 +37,41 @@ func (v *secrets) Alter(ctx context.Context, request *AlterSecretRequest) error return validateAndExec(v.client, ctx, opts) } +func (v *secrets) Drop(ctx context.Context, request *DropSecretRequest) error { + opts := request.toOpts() + return validateAndExec(v.client, ctx, opts) +} + +func (v *secrets) Show(ctx context.Context, request *ShowSecretRequest) ([]Secret, error) { + opts := request.toOpts() + dbRows, err := validateAndQuery[secretDBRow](v.client, ctx, opts) + if err != nil { + return nil, err + } + resultList := convertRows[secretDBRow, Secret](dbRows) + return resultList, nil +} + +func (v *secrets) ShowByID(ctx context.Context, id SchemaObjectIdentifier) (*Secret, error) { + // TODO: adjust request if e.g. LIKE is supported for the resource + secrets, err := v.Show(ctx, NewShowSecretRequest()) + if err != nil { + return nil, err + } + return collections.FindFirst(secrets, func(r Secret) bool { return r.Name == id.Name() }) +} + +func (v *secrets) Describe(ctx context.Context, id SchemaObjectIdentifier) (*SecretDetails, error) { + opts := &DescribeSecretOptions{ + name: id, + } + result, err := validateAndQueryOne[secretDetailsDBRow](v.client, ctx, opts) + if err != nil { + return nil, err + } + return result.convert(), nil +} + func (r *CreateWithOAuthClientCredentialsFlowSecretRequest) toOpts() *CreateWithOAuthClientCredentialsFlowSecretOptions { opts := &CreateWithOAuthClientCredentialsFlowSecretOptions{ OrReplace: r.OrReplace, @@ -141,3 +178,36 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { return opts } + +func (r *DropSecretRequest) toOpts() *DropSecretOptions { + opts := &DropSecretOptions{ + IfExists: r.IfExists, + name: r.name, + } + return opts +} + +func (r *ShowSecretRequest) toOpts() *ShowSecretOptions { + opts := &ShowSecretOptions{ + Like: r.Like, + In: r.In, + } + return opts +} + +func (r secretDBRow) convert() *Secret { + // TODO: Mapping + return &Secret{} +} + +func (r *DescribeSecretRequest) toOpts() *DescribeSecretOptions { + opts := &DescribeSecretOptions{ + name: r.name, + } + return opts +} + +func (r secretDetailsDBRow) convert() *SecretDetails { + // TODO: Mapping + return &SecretDetails{} +} diff --git a/pkg/sdk/secrets_validations_gen.go b/pkg/sdk/secrets_validations_gen.go index e703dbec57..c414a5cd6f 100644 --- a/pkg/sdk/secrets_validations_gen.go +++ b/pkg/sdk/secrets_validations_gen.go @@ -6,6 +6,9 @@ var ( _ validatable = new(CreateWithBasicAuthenticationSecretOptions) _ validatable = new(CreateWithGenericStringSecretOptions) _ validatable = new(AlterSecretOptions) + _ validatable = new(DropSecretOptions) + _ validatable = new(ShowSecretOptions) + _ validatable = new(DescribeSecretOptions) ) func (opts *CreateWithOAuthClientCredentialsFlowSecretOptions) validate() error { @@ -79,3 +82,33 @@ func (opts *AlterSecretOptions) validate() error { } return JoinErrors(errs...) } + +func (opts *DropSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + if !ValidObjectIdentifier(opts.name) { + errs = append(errs, ErrInvalidObjectIdentifier) + } + return JoinErrors(errs...) +} + +func (opts *ShowSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + return JoinErrors(errs...) +} + +func (opts *DescribeSecretOptions) validate() error { + if opts == nil { + return ErrNilOptions + } + var errs []error + if !ValidObjectIdentifier(opts.name) { + errs = append(errs, ErrInvalidObjectIdentifier) + } + return JoinErrors(errs...) +} From e4a0827ecd4e76cf340f95a7b77ac80222fc5a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 16 Sep 2024 11:39:47 +0200 Subject: [PATCH 08/34] all unit tests --- pkg/sdk/secrets_gen_test.go | 47 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index a07505fdb8..692737fe14 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -234,6 +234,7 @@ func TestSecrets_Alter(t *testing.T) { func TestSecrets_Drop(t *testing.T) { id := randomSchemaObjectIdentifier() + defaultOpts := func() *DropSecretOptions { return &DropSecretOptions{ name: id, @@ -244,7 +245,7 @@ func TestSecrets_Drop(t *testing.T) { var opts *DropSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) @@ -252,19 +253,17 @@ func TestSecrets_Drop(t *testing.T) { t.Run("basic", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + assertOptsValidAndSQLEquals(t, opts, "DROP SECRET %s", id.FullyQualifiedName()) }) t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfExists = Bool(true) + assertOptsValidAndSQLEquals(t, opts, "DROP SECRET IF EXISTS %s", id.FullyQualifiedName()) }) } func TestSecrets_Show(t *testing.T) { - // Minimal valid ShowSecretOptions defaultOpts := func() *ShowSecretOptions { return &ShowSecretOptions{} } @@ -276,24 +275,31 @@ func TestSecrets_Show(t *testing.T) { t.Run("basic", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS") }) - t.Run("all options", func(t *testing.T) { + t.Run("show with like", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.Like = &Like{ + Pattern: String("pattern"), + } + assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS LIKE 'pattern'") + }) + + t.Run("show with in", func(t *testing.T) { + opts := defaultOpts() + opts.In = &In{ + Account: Bool(true), + } + assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS IN ACCOUNT") }) } func TestSecrets_Describe(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid DescribeSecretOptions + defaultOpts := func() *DescribeSecretOptions { return &DescribeSecretOptions{ - name: id, } } @@ -302,21 +308,14 @@ func TestSecrets_Describe(t *testing.T) { var opts *DescribeSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + assertOptsValidAndSQLEquals(t, opts, "DESCRIBE SECRET %s", id.FullyQualifiedName()) }) } From 3bb8c859e55a5c2ccf180234b9c56f35b5f947f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 16 Sep 2024 16:10:25 +0200 Subject: [PATCH 09/34] init for integration tests --- pkg/acceptance/helpers/secret_client.go | 19 +++ pkg/acceptance/helpers/test_client.go | 2 + pkg/sdk/client.go | 1 + pkg/sdk/secrets_gen_integration_test.go | 43 ------ .../testint/secrets_gen_integration_test.go | 135 ++++++++++++++++++ 5 files changed, 157 insertions(+), 43 deletions(-) create mode 100644 pkg/acceptance/helpers/secret_client.go delete mode 100644 pkg/sdk/secrets_gen_integration_test.go create mode 100644 pkg/sdk/testint/secrets_gen_integration_test.go diff --git a/pkg/acceptance/helpers/secret_client.go b/pkg/acceptance/helpers/secret_client.go new file mode 100644 index 0000000000..e800d6f59f --- /dev/null +++ b/pkg/acceptance/helpers/secret_client.go @@ -0,0 +1,19 @@ +package helpers + +import "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + +type SecretClient struct { + context *TestClientContext + ids *IdsGenerator +} + +func NewSecretClient(context *TestClientContext, idsGenerator *IdsGenerator) *SecretClient { + return &SecretClient{ + context: context, + ids: idsGenerator, + } +} + +func (c *SecretClient) client() sdk.Secrets { + return c.context.client.Secrets +} diff --git a/pkg/acceptance/helpers/test_client.go b/pkg/acceptance/helpers/test_client.go index 975c74a061..63b59097ed 100644 --- a/pkg/acceptance/helpers/test_client.go +++ b/pkg/acceptance/helpers/test_client.go @@ -47,6 +47,7 @@ type TestClient struct { Role *RoleClient RowAccessPolicy *RowAccessPolicyClient Schema *SchemaClient + Secret *SecretClient SecurityIntegration *SecurityIntegrationClient SessionPolicy *SessionPolicyClient Share *ShareClient @@ -112,6 +113,7 @@ func NewTestClient(c *sdk.Client, database string, schema string, warehouse stri Role: NewRoleClient(context, idsGenerator), RowAccessPolicy: NewRowAccessPolicyClient(context, idsGenerator), Schema: NewSchemaClient(context, idsGenerator), + Secret: NewSecretClient(context, idsGenerator), SecurityIntegration: NewSecurityIntegrationClient(context, idsGenerator), SessionPolicy: NewSessionPolicyClient(context, idsGenerator), Share: NewShareClient(context, idsGenerator), diff --git a/pkg/sdk/client.go b/pkg/sdk/client.go index 6f2e57200e..5d1ddaa887 100644 --- a/pkg/sdk/client.go +++ b/pkg/sdk/client.go @@ -75,6 +75,7 @@ type Client struct { Roles Roles RowAccessPolicies RowAccessPolicies Schemas Schemas + Secrets Secrets SecurityIntegrations SecurityIntegrations Sequences Sequences SessionPolicies SessionPolicies diff --git a/pkg/sdk/secrets_gen_integration_test.go b/pkg/sdk/secrets_gen_integration_test.go deleted file mode 100644 index 4474555b36..0000000000 --- a/pkg/sdk/secrets_gen_integration_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package sdk - -import "testing" - -func TestInt_Secrets(t *testing.T) { - // TODO: prepare common resources - - t.Run("CreateWithOAuthClientCredentialsFlow", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("CreateWithBasicAuthentication", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("CreateWithGenericString", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Alter", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Drop", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Show", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("ShowByID", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Describe", func(t *testing.T) { - // TODO: fill me - }) -} diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go new file mode 100644 index 0000000000..898ee92414 --- /dev/null +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -0,0 +1,135 @@ +package testint + +import ( + "database/sql" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) + +func TestInt_Secrets(t *testing.T) { + client := testClient(t) + ctx := testContext(t) + + cleanupSecret := func(id sdk.SchemaObjectIdentifier) { + t.Cleanup(func() { + err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) + assert.NoError(t, err) + }) + } + + assertSecret := func(t *testing.T, s *sdk.Secret, id sdk.SchemaObjectIdentifier, secretType, comment string) { + t.Helper() + assert.NotEmpty(t, s.CreatedOn) + assert.NotEmpty(t, s.DatabaseName) + assert.NotEmpty(t, s.SchemaName) + assert.NotEmpty(t, s.OwnerRoleType) + assert.NotEmpty(t, s.Owner) + assert.Equal(t, id.Name(), s.Name) + assert.Equal(t, secretType, s.SecretType) + assert.Equal(t, comment, s.Comment) + } + + type secretDetails struct { + Name string + Comment sql.NullString + SecretType string + Username sql.NullString + OauthAccessTokenExpiryTime sql.NullString + OauthRefreshTokenExpiryTime sql.NullString + OauthScopes sql.NullString + IntegrationName sql.NullString + } + + assertBasicAuth := func(details *sdk.SecretDetails, d secretDetails) { + assert.Equal(t, d.Name, details.Name) + assert.Equal(t, d.Comment, details.Comment) + assert.Equal(t, d.SecretType, details.SecretType) + assert.Equal(t, d.Username, details.Username) + assert.Equal(t, d.OauthAccessTokenExpiryTime, details.OauthAccessTokenExpiryTime) + assert.Equal(t, d.OauthRefreshTokenExpiryTime, details.OauthRefreshTokenExpiryTime) + assert.Equal(t, d.OauthScopes, details.OauthScopes) + assert.Equal(t, d.IntegrationName, details.IntegrationName) + } + _ = assertBasicAuth + + /* + createOAuthClientCredentialsFlowSecret := func(id sdk.SchemaObjectIdentifier, si sdk.CreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest) { + //TODO + } + + createBasicAuthenticationSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier, username, password string) *sdk.Secret { + t.Helper() + + err := client.Secrets.CreateWithBasicAuthentication(ctx, sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password)) + require.NoError(t, err) + cleanupSecret(id) + + secret, err := client.Secrets.ShowByID(ctx, id) + return secret + } + */ + + t.Run("Create secret with OAuth Client Credentials Flow", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Create With Basic Authentication", func(t *testing.T) { + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + comment := random.Comment() + + request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, "foo", "foo").WithComment(comment).WithIfNotExists(true) + // todo: secrets = nil + err := client.Secrets.CreateWithBasicAuthentication(ctx, request) + require.NoError(t, err) + cleanupSecret(id) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + assertSecret(t, secret, id, "PASSWORD", comment) + /* + details, err := client.Secrets.Describe(ctx, id) + + assertBasicAuth(details, secretDetails{ + Name: id.FullyQualifiedName(), + Comment: sql.NullString{String: comment}, + SecretType: "PASSWORD", + Username: sql.NullString{String: "foo"}, + OauthAccessTokenExpiryTime: sql.NullString{}, + OauthRefreshTokenExpiryTime: sql.NullString{}, + OauthScopes: sql.NullString{}, + IntegrationName: sql.NullString{}, + }) + */ + }) + + t.Run("CreateWithGenericString", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Alter", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Drop", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Show", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("ShowByID", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Describe", func(t *testing.T) { + // TODO: fill me + }) +} From 4130618bec6f9fed1d72319164d0fb03d945e535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 17 Sep 2024 11:02:32 +0200 Subject: [PATCH 10/34] added secret to client.go and created secret_client --- pkg/acceptance/helpers/secret_client.go | 38 ++++++++++++++++++++++++- pkg/sdk/client.go | 1 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/pkg/acceptance/helpers/secret_client.go b/pkg/acceptance/helpers/secret_client.go index e800d6f59f..aa98ceafb1 100644 --- a/pkg/acceptance/helpers/secret_client.go +++ b/pkg/acceptance/helpers/secret_client.go @@ -1,6 +1,13 @@ package helpers -import "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +import ( + "context" + "errors" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) type SecretClient struct { context *TestClientContext @@ -17,3 +24,32 @@ func NewSecretClient(context *TestClientContext, idsGenerator *IdsGenerator) *Se func (c *SecretClient) client() sdk.Secrets { return c.context.client.Secrets } + +func (c *SecretClient) CreateSecreteWithBasicFlow(t *testing.T, id sdk.SchemaObjectIdentifier, username, password string) (*sdk.Secret, func()) { + t.Helper() + ctx := context.Background() + request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password) + + err := c.client().CreateWithBasicAuthentication(ctx, request) + require.NoError(t, err) + + secret, err := c.client().ShowByID(ctx, id) + require.NoError(t, err) + + return secret, c.CleanupSecretFunc(t, id) +} + +func (c *SecretClient) CleanupSecretFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + ctx := context.Background() + + return func() { + _, err := c.client().ShowByID(ctx, id) + if errors.Is(err, sdk.ErrObjectNotExistOrAuthorized) { + return + } + + err = c.client().Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) + assert.NoError(t, err) + } +} diff --git a/pkg/sdk/client.go b/pkg/sdk/client.go index 5d1ddaa887..b5a76425c9 100644 --- a/pkg/sdk/client.go +++ b/pkg/sdk/client.go @@ -236,6 +236,7 @@ func (c *Client) initialize() { c.Roles = &roles{client: c} c.RowAccessPolicies = &rowAccessPolicies{client: c} c.Schemas = &schemas{client: c} + c.Secrets = &secrets{client: c} c.SecurityIntegrations = &securityIntegrations{client: c} c.Sequences = &sequences{client: c} c.SessionPolicies = &sessionPolicies{client: c} From fc85c660e43d8546f161ea8f86aa75c4295cb53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 17 Sep 2024 11:03:36 +0200 Subject: [PATCH 11/34] added like and in to showByID for secret --- pkg/sdk/secrets_impl_gen.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index dc31263fc8..b1c7418ae2 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -53,8 +53,8 @@ func (v *secrets) Show(ctx context.Context, request *ShowSecretRequest) ([]Secre } func (v *secrets) ShowByID(ctx context.Context, id SchemaObjectIdentifier) (*Secret, error) { - // TODO: adjust request if e.g. LIKE is supported for the resource - secrets, err := v.Show(ctx, NewShowSecretRequest()) + request := NewShowSecretRequest().WithIn(In{Schema: id.SchemaId()}).WithLike(Like{String(id.Name())}) + secrets, err := v.Show(ctx, request) if err != nil { return nil, err } From aa645112a119676b5ab9ccc23c8f4f614717210f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 17 Sep 2024 11:03:55 +0200 Subject: [PATCH 12/34] init for integration tests --- .../testint/secrets_gen_integration_test.go | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 898ee92414..bb271f7b9e 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -13,23 +13,23 @@ func TestInt_Secrets(t *testing.T) { client := testClient(t) ctx := testContext(t) - cleanupSecret := func(id sdk.SchemaObjectIdentifier) { - t.Cleanup(func() { + cleanupSecret := func(id sdk.SchemaObjectIdentifier) func() { + return func() { err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) - assert.NoError(t, err) - }) + require.NoError(t, err) + } } - assertSecret := func(t *testing.T, s *sdk.Secret, id sdk.SchemaObjectIdentifier, secretType, comment string) { + assertSecret := func(t *testing.T, s *sdk.Secret, expectedId sdk.SchemaObjectIdentifier, expectedSecretType, expectedComment string) { t.Helper() + assert.Equal(t, expectedId.Name(), s.Name) + assert.Equal(t, expectedSecretType, s.SecretType) + assert.Equal(t, expectedComment, s.Comment) assert.NotEmpty(t, s.CreatedOn) assert.NotEmpty(t, s.DatabaseName) assert.NotEmpty(t, s.SchemaName) assert.NotEmpty(t, s.OwnerRoleType) assert.NotEmpty(t, s.Owner) - assert.Equal(t, id.Name(), s.Name) - assert.Equal(t, secretType, s.SecretType) - assert.Equal(t, comment, s.Comment) } type secretDetails struct { @@ -56,18 +56,21 @@ func TestInt_Secrets(t *testing.T) { _ = assertBasicAuth /* - createOAuthClientCredentialsFlowSecret := func(id sdk.SchemaObjectIdentifier, si sdk.CreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest) { - //TODO - } + createOAuthClientCredentialsFlowSecret := func(id sdk.SchemaObjectIdentifier, si sdk.CreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest) { + //TODO + } - createBasicAuthenticationSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier, username, password string) *sdk.Secret { + createBasicAuthenticationSecret := func(t *testing.T, username, password string) *sdk.Secret { t.Helper() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() err := client.Secrets.CreateWithBasicAuthentication(ctx, sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password)) require.NoError(t, err) - cleanupSecret(id) + t.Cleanup(cleanupSecret(id)) secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + return secret } */ @@ -83,32 +86,33 @@ func TestInt_Secrets(t *testing.T) { t.Run("Create With Basic Authentication", func(t *testing.T) { id := testClientHelper().Ids.RandomSchemaObjectIdentifier() comment := random.Comment() - request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, "foo", "foo").WithComment(comment).WithIfNotExists(true) - // todo: secrets = nil + err := client.Secrets.CreateWithBasicAuthentication(ctx, request) require.NoError(t, err) - cleanupSecret(id) + t.Cleanup(cleanupSecret(id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) + assertSecret(t, secret, id, "PASSWORD", comment) - /* - details, err := client.Secrets.Describe(ctx, id) - - assertBasicAuth(details, secretDetails{ - Name: id.FullyQualifiedName(), - Comment: sql.NullString{String: comment}, - SecretType: "PASSWORD", - Username: sql.NullString{String: "foo"}, - OauthAccessTokenExpiryTime: sql.NullString{}, - OauthRefreshTokenExpiryTime: sql.NullString{}, - OauthScopes: sql.NullString{}, - IntegrationName: sql.NullString{}, - }) - */ }) + /* + details, err := client.Secrets.Describe(ctx, id) + + assertBasicAuth(details, secretDetails{ + Name: id.FullyQualifiedName(), + Comment: sql.NullString{String: comment}, + SecretType: "PASSWORD", + Username: sql.NullString{String: "foo"}, + OauthAccessTokenExpiryTime: sql.NullString{}, + OauthRefreshTokenExpiryTime: sql.NullString{}, + OauthScopes: sql.NullString{}, + IntegrationName: sql.NullString{}, + }) + */ + t.Run("CreateWithGenericString", func(t *testing.T) { // TODO: fill me }) From ab8bee1867cc707dfb8626c517bb3491173ca35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 17 Sep 2024 11:04:05 +0200 Subject: [PATCH 13/34] secret_def changes --- pkg/sdk/secrets_def.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 9d3ae947c9..8a0909d988 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -15,10 +15,9 @@ var secretDbRow = g.DbStruct("secretDBRow"). Field("owner", "string"). Field("comment", "sql.NullString"). Field("secret_type", "string"). - Field("oauth_scopes", "sql.NullString"). // its a list tho + Field("oauth_scopes", "[]string"). // its a list tho Field("owner_role_type", "string") -// cannot name 'secret' due to clash in common_types.go var secret = g.PlainStruct("Secret"). Field("CreatedOn", "string"). Field("Name", "string"). @@ -27,7 +26,7 @@ var secret = g.PlainStruct("Secret"). Field("Owner", "string"). Field("Comment", "string"). Field("SecretType", "string"). - Field("OauthScopes", "sql.NullString"). + Field("OauthScopes", "[]string"). Field("OwnerRoleType", "string") var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). @@ -63,14 +62,12 @@ var secretSet = g.NewQueryStruct("SecretSet"). OptionalQueryStructField( "SetForOAuthClientCredentialsFlow", g.NewQueryStruct("SetForOAuthClientCredentialsFlow"). - //OptionalQueryStructField("OAuthScopes", secretsIntegrationScopes, g.ParameterOptions().MustParentheses().SQL("OAUTH_SCOPES")), ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses().Required()), g.KeywordOptions(), ). OptionalQueryStructField( "SetForOAuthAuthorizationFlow", g.NewQueryStruct("SetForOAuthAuthorizationFlow"). - //optional or just TextAssignment()?? OptionalTextAssignment("OAUTH_REFRESH_TOKEN", g.ParameterOptions().SingleQuotes()). OptionalTextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().SingleQuotes()), g.KeywordOptions(), From 3541c70e05de487f452745c42b87a1c11e6a8f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 17 Sep 2024 16:12:43 +0200 Subject: [PATCH 14/34] tests for two methods of creating secret --- pkg/sdk/secrets_def.go | 18 +- pkg/sdk/secrets_impl_gen.go | 34 +++- .../testint/secrets_gen_integration_test.go | 158 +++++++++++++----- 3 files changed, 162 insertions(+), 48 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 8a0909d988..3bed2d18e1 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -15,7 +15,7 @@ var secretDbRow = g.DbStruct("secretDBRow"). Field("owner", "string"). Field("comment", "sql.NullString"). Field("secret_type", "string"). - Field("oauth_scopes", "[]string"). // its a list tho + Field("oauth_scopes", "sql.NullString"). // its a list tho Field("owner_role_type", "string") var secret = g.PlainStruct("Secret"). @@ -26,7 +26,7 @@ var secret = g.PlainStruct("Secret"). Field("Owner", "string"). Field("Comment", "string"). Field("SecretType", "string"). - Field("OauthScopes", "[]string"). + Field("OauthScopes", "sql.NullString"). Field("OwnerRoleType", "string") var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). @@ -87,7 +87,7 @@ var secretSet = g.NewQueryStruct("SecretSet"). ). WithValidation(g.ExactlyOneValueSet, "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString") -// TODO: unset doest work, need to use "SET COMMENT = NULL" +// TODO: UNSET doest work, need to use "SET COMMENT = NULL" var secretUnset = g.NewQueryStruct("SecretUnset"). //OptionalSQL("UNSET COMMENT") PredefinedQueryStructField("Comment", "*bool", g.KeywordOptions().SQL("SET COMMENT = NULL")) @@ -199,6 +199,18 @@ var SecretsDef = g.NewInterface( "https://docs.snowflake.com/en/sql-reference/sql/desc-secret", secretDetailsDbRow, secretDetails, + + /* + g.DescriptionMappingKindSlice, + "https://docs.snowflake.com/en/sql-reference/sql/desc-secret", + g.DbStruct("secretDetailsRow"). + Field("property", "string"). + Field("value", "sql.NullString"), + g.PlainStruct("SecretDetails"). + Field("Property", "string"). + Field("Value", "string"), + */ + g.NewQueryStruct("DescribeSecret"). Describe(). SQL("SECRET"). diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index b1c7418ae2..1386955543 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -196,8 +196,22 @@ func (r *ShowSecretRequest) toOpts() *ShowSecretOptions { } func (r secretDBRow) convert() *Secret { - // TODO: Mapping - return &Secret{} + s := &Secret{ + CreatedOn: r.CreatedOn, + Name: r.Name, + SchemaName: r.SchemaName, + DatabaseName: r.DatabaseName, + Owner: r.Owner, + SecretType: r.SecretType, + OwnerRoleType: r.OwnerRoleType, + } + if r.Comment.Valid { + s.Comment = r.Comment.String + } + if r.OauthScopes.Valid { + s.OauthScopes = r.OauthScopes + } + return s } func (r *DescribeSecretRequest) toOpts() *DescribeSecretOptions { @@ -208,6 +222,18 @@ func (r *DescribeSecretRequest) toOpts() *DescribeSecretOptions { } func (r secretDetailsDBRow) convert() *SecretDetails { - // TODO: Mapping - return &SecretDetails{} + return &SecretDetails{ + CreatedOn: r.CreatedOn, + Name: r.Name, + SchemaName: r.SchemaName, + DatabaseName: r.DatabaseName, + Owner: r.Owner, + Comment: r.Comment, + SecretType: r.SecretType, + Username: r.Username, + OauthAccessTokenExpiryTime: r.OauthAccessTokenExpiryTime, + OauthRefreshTokenExpiryTime: r.OauthRefreshTokenExpiryTime, + OauthScopes: r.OauthScopes, + IntegrationName: r.IntegrationName, + } } diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index bb271f7b9e..696cdf2a2c 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -12,6 +12,20 @@ import ( func TestInt_Secrets(t *testing.T) { client := testClient(t) ctx := testContext(t) + integrationId := testClientHelper().Ids.RandomAccountObjectIdentifier() + + cleanupIntegration := func(t *testing.T, integrationId sdk.AccountObjectIdentifier) func() { + return func() { + err := client.SecurityIntegrations.Drop(ctx, sdk.NewDropSecurityIntegrationRequest(integrationId).WithIfExists(true)) + require.NoError(t, err) + } + } + + integrationRequeset := sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). + WithOauthAllowedScopes([]sdk.AllowedScope{{"foo"}, {"bar"}}) + err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow(ctx, integrationRequeset) + require.NoError(t, err) + t.Cleanup(cleanupIntegration(t, integrationId)) cleanupSecret := func(id sdk.SchemaObjectIdentifier) func() { return func() { @@ -32,6 +46,40 @@ func TestInt_Secrets(t *testing.T) { assert.NotEmpty(t, s.Owner) } + createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integration sdk.AccountObjectIdentifier, scopes []sdk.SecurityIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + t.Helper() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integration, scopes) + if with != nil { + with(request) + } + err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupSecret(id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret, id + } + + createSecretWithBasicAuthorization := func(t *testing.T, username, password string, with func(*sdk.CreateWithBasicAuthenticationSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + t.Helper() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password) + if with != nil { + with(request) + } + err := client.Secrets.CreateWithBasicAuthentication(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupSecret(id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret, id + } + type secretDetails struct { Name string Comment sql.NullString @@ -43,75 +91,103 @@ func TestInt_Secrets(t *testing.T) { IntegrationName sql.NullString } - assertBasicAuth := func(details *sdk.SecretDetails, d secretDetails) { - assert.Equal(t, d.Name, details.Name) - assert.Equal(t, d.Comment, details.Comment) - assert.Equal(t, d.SecretType, details.SecretType) - assert.Equal(t, d.Username, details.Username) - assert.Equal(t, d.OauthAccessTokenExpiryTime, details.OauthAccessTokenExpiryTime) - assert.Equal(t, d.OauthRefreshTokenExpiryTime, details.OauthRefreshTokenExpiryTime) - assert.Equal(t, d.OauthScopes, details.OauthScopes) - assert.Equal(t, d.IntegrationName, details.IntegrationName) + assertSecretDetails := func(actual *sdk.SecretDetails, expected secretDetails) { + assert.Equal(t, expected.Name, actual.Name) + assert.Equal(t, expected.Comment, actual.Comment) + assert.Equal(t, expected.SecretType, actual.SecretType) + assert.Equal(t, expected.Username, actual.Username) + assert.Equal(t, expected.OauthAccessTokenExpiryTime, actual.OauthAccessTokenExpiryTime) + assert.Equal(t, expected.OauthRefreshTokenExpiryTime, actual.OauthRefreshTokenExpiryTime) + assert.Equal(t, expected.OauthScopes, actual.OauthScopes) + assert.Equal(t, expected.IntegrationName, actual.IntegrationName) } - _ = assertBasicAuth - /* - createOAuthClientCredentialsFlowSecret := func(id sdk.SchemaObjectIdentifier, si sdk.CreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest) { - //TODO - } + t.Run("Create secret with OAuth Client Credentials Flow", func(t *testing.T) { + scopes := []sdk.SecurityIntegrationScope{{"foo"}, {"bar"}} + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, scopes, func(req *sdk.CreateWithOAuthClientCredentialsFlowSecretRequest) { + req.WithComment("a"). + WithIfNotExists(true) + }) + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + Comment: sql.NullString{String: "a", Valid: true}, + SecretType: "OAUTH2", + OauthScopes: sql.NullString{String: "[foo, bar]", Valid: true}, + IntegrationName: sql.NullString{String: integrationId.Name(), Valid: true}, + }) - createBasicAuthenticationSecret := func(t *testing.T, username, password string) *sdk.Secret { - t.Helper() - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + assertSecret(t, secret, id, "OAUTH2", "a") + }) - err := client.Secrets.CreateWithBasicAuthentication(ctx, sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password)) - require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) + // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret should inherit security_integration scopes, but it does not + t.Run("CreateSecretWithOAuthClientCredentialsFlow: No Scopes Specified", func(t *testing.T) { + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{}, nil) - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) - return secret - } - */ + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + OauthScopes: sql.NullString{}, + IntegrationName: sql.NullString{String: integrationId.Name(), Valid: true}, + }) - t.Run("Create secret with OAuth Client Credentials Flow", func(t *testing.T) { - // TODO: fill me + assertSecret(t, secret, id, "OAUTH2", "") }) t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { // TODO: fill me }) - t.Run("Create With Basic Authentication", func(t *testing.T) { - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + t.Run("CreateWithBasicAuthentication", func(t *testing.T) { comment := random.Comment() - request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, "foo", "foo").WithComment(comment).WithIfNotExists(true) - - err := client.Secrets.CreateWithBasicAuthentication(ctx, request) + secret, id := createSecretWithBasicAuthorization(t, "foo", "foo", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { + req.WithComment(comment). + WithIfNotExists(true) + }) + details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + Comment: sql.NullString{String: comment, Valid: true}, + SecretType: "PASSWORD", + Username: sql.NullString{String: "foo", Valid: true}, + OauthAccessTokenExpiryTime: sql.NullString{}, + OauthRefreshTokenExpiryTime: sql.NullString{}, + OauthScopes: sql.NullString{}, + IntegrationName: sql.NullString{}, + }) assertSecret(t, secret, id, "PASSWORD", comment) }) - /* + t.Run("CreateWithBasicAuthentication: Empty Username and Password", func(t *testing.T) { + comment := random.Comment() + secret, id := createSecretWithBasicAuthorization(t, "", "", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { + req.WithComment(comment). + WithIfNotExists(true) + }) details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) - assertBasicAuth(details, secretDetails{ - Name: id.FullyQualifiedName(), - Comment: sql.NullString{String: comment}, + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + Comment: sql.NullString{String: comment, Valid: true}, SecretType: "PASSWORD", - Username: sql.NullString{String: "foo"}, + Username: sql.NullString{String: "", Valid: true}, OauthAccessTokenExpiryTime: sql.NullString{}, OauthRefreshTokenExpiryTime: sql.NullString{}, OauthScopes: sql.NullString{}, IntegrationName: sql.NullString{}, }) - */ + + assertSecret(t, secret, id, "PASSWORD", comment) + }) t.Run("CreateWithGenericString", func(t *testing.T) { // TODO: fill me From 180a7ce03118e63988f826da1a835a2ff264566a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Wed, 18 Sep 2024 10:45:42 +0200 Subject: [PATCH 15/34] changed refresh token expiry time from string to time.Time --- pkg/sdk/secrets_def.go | 8 +- .../testint/secrets_gen_integration_test.go | 124 ++++++++++++------ 2 files changed, 89 insertions(+), 43 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 3bed2d18e1..9ecfb0bf46 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -38,8 +38,8 @@ var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). Field("comment", "sql.NullString"). Field("secret_type", "string"). Field("username", "sql.NullString"). - Field("oauth_access_token_expiry_time", "sql.NullString"). - Field("oauth_refresh_token_expiry_time", "sql.NullString"). + Time("oauth_access_token_expiry_time"). + Time("oauth_refresh_token_expiry_time"). Field("oauth_scopes", "sql.NullString"). // its a list tho Field("integration_name", "sql.NullString") @@ -52,8 +52,8 @@ var secretDetails = g.PlainStruct("SecretDetails"). Field("Comment", "sql.NullString"). Field("SecretType", "string"). Field("Username", "sql.NullString"). - Field("OauthAccessTokenExpiryTime", "sql.NullString"). - Field("OauthRefreshTokenExpiryTime", "sql.NullString"). + Time("OauthAccessTokenExpiryTime"). + Time("OauthRefreshTokenExpiryTime"). Field("OauthScopes", "sql.NullString"). // its a list tho Field("IntegrationName", "sql.NullString") diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 696cdf2a2c..d86270636e 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -1,12 +1,12 @@ package testint import ( - "database/sql" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "testing" + "time" ) func TestInt_Secrets(t *testing.T) { @@ -21,9 +21,9 @@ func TestInt_Secrets(t *testing.T) { } } - integrationRequeset := sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). + integrationRequest := sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). WithOauthAllowedScopes([]sdk.AllowedScope{{"foo"}, {"bar"}}) - err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow(ctx, integrationRequeset) + err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow(ctx, integrationRequest) require.NoError(t, err) t.Cleanup(cleanupIntegration(t, integrationId)) @@ -46,10 +46,10 @@ func TestInt_Secrets(t *testing.T) { assert.NotEmpty(t, s.Owner) } - createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integration sdk.AccountObjectIdentifier, scopes []sdk.SecurityIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, scopes []sdk.SecurityIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integration, scopes) + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, scopes) if with != nil { with(request) } @@ -63,6 +63,23 @@ func TestInt_Secrets(t *testing.T) { return secret, id } + createSecretWithOAuthAuthorizationCodeFlow := func(t *testing.T, refreshToken, refreshTokenExpiryTime string, integrationId sdk.AccountObjectIdentifier, with func(*sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + t.Helper() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithOAuthAuthorizationCodeFlowSecretRequest(id, refreshToken, refreshTokenExpiryTime, integrationId) + if with != nil { + with(request) + } + err := client.Secrets.CreateWithOAuthAuthorizationCodeFlow(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupSecret(id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret, id + } + createSecretWithBasicAuthorization := func(t *testing.T, username, password string, with func(*sdk.CreateWithBasicAuthenticationSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() @@ -82,24 +99,24 @@ func TestInt_Secrets(t *testing.T) { type secretDetails struct { Name string - Comment sql.NullString + Comment string SecretType string - Username sql.NullString - OauthAccessTokenExpiryTime sql.NullString - OauthRefreshTokenExpiryTime sql.NullString - OauthScopes sql.NullString - IntegrationName sql.NullString + Username string + OauthAccessTokenExpiryTime time.Time + OauthRefreshTokenExpiryTime time.Time + OauthScopes string + IntegrationName string } assertSecretDetails := func(actual *sdk.SecretDetails, expected secretDetails) { assert.Equal(t, expected.Name, actual.Name) - assert.Equal(t, expected.Comment, actual.Comment) + assert.Equal(t, expected.Comment, actual.Comment.String) assert.Equal(t, expected.SecretType, actual.SecretType) - assert.Equal(t, expected.Username, actual.Username) - assert.Equal(t, expected.OauthAccessTokenExpiryTime, actual.OauthAccessTokenExpiryTime) - assert.Equal(t, expected.OauthRefreshTokenExpiryTime, actual.OauthRefreshTokenExpiryTime) - assert.Equal(t, expected.OauthScopes, actual.OauthScopes) - assert.Equal(t, expected.IntegrationName, actual.IntegrationName) + assert.Equal(t, expected.Username, actual.Username.String) + assert.Equal(t, expected.OauthAccessTokenExpiryTime.String(), actual.OauthAccessTokenExpiryTime.String) + assert.Equal(t, expected.OauthRefreshTokenExpiryTime.String(), actual.OauthRefreshTokenExpiryTime.String) + assert.Equal(t, expected.OauthScopes, actual.OauthScopes.String) + assert.Equal(t, expected.IntegrationName, actual.IntegrationName.String) } t.Run("Create secret with OAuth Client Credentials Flow", func(t *testing.T) { @@ -113,10 +130,10 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails(details, secretDetails{ Name: id.Name(), - Comment: sql.NullString{String: "a", Valid: true}, + Comment: "a", SecretType: "OAUTH2", - OauthScopes: sql.NullString{String: "[foo, bar]", Valid: true}, - IntegrationName: sql.NullString{String: integrationId.Name(), Valid: true}, + OauthScopes: "[foo, bar]", + IntegrationName: integrationId.Name(), }) assertSecret(t, secret, id, "OAUTH2", "a") @@ -132,17 +149,55 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails(details, secretDetails{ Name: id.Name(), SecretType: "OAUTH2", - OauthScopes: sql.NullString{}, - IntegrationName: sql.NullString{String: integrationId.Name(), Valid: true}, + IntegrationName: integrationId.Name(), }) assertSecret(t, secret, id, "OAUTH2", "") }) t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { - // TODO: fill me + secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, "foo", "2024-09-20", integrationId, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { + req.WithComment("a"). + WithIfNotExists(true) + }) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + Comment: "a", + OauthRefreshTokenExpiryTime: time.Time{}, //"2024-09-20", + IntegrationName: integrationId.Name(), + }) + + assertSecret(t, secret, id, "OAUTH2", "") }) + /* + //require.EqualError(t, err, "Invalid data/time format string") + t.Run("CreateWithOAuthAuthorizationCodeFlow: Invalid date/time format string", func(t *testing.T) { + secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { + req.WithComment("a"). + WithIfNotExists(true) + }) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + OauthAccessTokenExpiryTime: "foo", + OauthRefreshTokenExpiryTime: "foo", + IntegrationName: integrationId.Name(), + }) + + assertSecret(t, secret, id, "OAUTH2", "") + }) + */ + t.Run("CreateWithBasicAuthentication", func(t *testing.T) { comment := random.Comment() secret, id := createSecretWithBasicAuthorization(t, "foo", "foo", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { @@ -153,14 +208,10 @@ func TestInt_Secrets(t *testing.T) { require.NoError(t, err) assertSecretDetails(details, secretDetails{ - Name: id.Name(), - Comment: sql.NullString{String: comment, Valid: true}, - SecretType: "PASSWORD", - Username: sql.NullString{String: "foo", Valid: true}, - OauthAccessTokenExpiryTime: sql.NullString{}, - OauthRefreshTokenExpiryTime: sql.NullString{}, - OauthScopes: sql.NullString{}, - IntegrationName: sql.NullString{}, + Name: id.Name(), + Comment: comment, + SecretType: "PASSWORD", + Username: "foo", }) assertSecret(t, secret, id, "PASSWORD", comment) @@ -176,14 +227,9 @@ func TestInt_Secrets(t *testing.T) { require.NoError(t, err) assertSecretDetails(details, secretDetails{ - Name: id.Name(), - Comment: sql.NullString{String: comment, Valid: true}, - SecretType: "PASSWORD", - Username: sql.NullString{String: "", Valid: true}, - OauthAccessTokenExpiryTime: sql.NullString{}, - OauthRefreshTokenExpiryTime: sql.NullString{}, - OauthScopes: sql.NullString{}, - IntegrationName: sql.NullString{}, + Name: id.Name(), + Comment: comment, + SecretType: "PASSWORD", }) assertSecret(t, secret, id, "PASSWORD", comment) From 7a9ad924cba2e5d64357a4d33302d53f9bbc2a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Thu, 19 Sep 2024 10:26:08 +0200 Subject: [PATCH 16/34] added remaining integration tests --- pkg/sdk/secrets_def.go | 25 +- pkg/sdk/secrets_gen.go | 9 +- .../testint/secrets_gen_integration_test.go | 565 +++++++++++++++--- 3 files changed, 505 insertions(+), 94 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 9ecfb0bf46..ddd1fa95fd 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -15,7 +15,7 @@ var secretDbRow = g.DbStruct("secretDBRow"). Field("owner", "string"). Field("comment", "sql.NullString"). Field("secret_type", "string"). - Field("oauth_scopes", "sql.NullString"). // its a list tho + Field("oauth_scopes", "sql.NullString"). Field("owner_role_type", "string") var secret = g.PlainStruct("Secret"). @@ -40,7 +40,7 @@ var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). Field("username", "sql.NullString"). Time("oauth_access_token_expiry_time"). Time("oauth_refresh_token_expiry_time"). - Field("oauth_scopes", "sql.NullString"). // its a list tho + Field("oauth_scopes", "sql.NullString"). Field("integration_name", "sql.NullString") var secretDetails = g.PlainStruct("SecretDetails"). @@ -52,9 +52,9 @@ var secretDetails = g.PlainStruct("SecretDetails"). Field("Comment", "sql.NullString"). Field("SecretType", "string"). Field("Username", "sql.NullString"). - Time("OauthAccessTokenExpiryTime"). - Time("OauthRefreshTokenExpiryTime"). - Field("OauthScopes", "sql.NullString"). // its a list tho + Field("OauthAccessTokenExpiryTime", "*time.Time"). + Field("OauthRefreshTokenExpiryTime", "*time.Time"). + Field("OauthScopes", "sql.NullString"). Field("IntegrationName", "sql.NullString") var secretSet = g.NewQueryStruct("SecretSet"). @@ -87,9 +87,8 @@ var secretSet = g.NewQueryStruct("SecretSet"). ). WithValidation(g.ExactlyOneValueSet, "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString") -// TODO: UNSET doest work, need to use "SET COMMENT = NULL" +// UNSET doest work, need to use "SET COMMENT = NULL" var secretUnset = g.NewQueryStruct("SecretUnset"). - //OptionalSQL("UNSET COMMENT") PredefinedQueryStructField("Comment", "*bool", g.KeywordOptions().SQL("SET COMMENT = NULL")) var SecretsDef = g.NewInterface( @@ -199,18 +198,6 @@ var SecretsDef = g.NewInterface( "https://docs.snowflake.com/en/sql-reference/sql/desc-secret", secretDetailsDbRow, secretDetails, - - /* - g.DescriptionMappingKindSlice, - "https://docs.snowflake.com/en/sql-reference/sql/desc-secret", - g.DbStruct("secretDetailsRow"). - Field("property", "string"). - Field("value", "sql.NullString"), - g.PlainStruct("SecretDetails"). - Field("Property", "string"). - Field("Value", "string"), - */ - g.NewQueryStruct("DescribeSecret"). Describe(). SQL("SECRET"). diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index 6ff0313c1e..b90ac53ea3 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -3,6 +3,7 @@ package sdk import ( "context" "database/sql" + "time" ) type Secrets interface { @@ -159,8 +160,8 @@ type secretDetailsDBRow struct { Comment sql.NullString `db:"comment"` SecretType string `db:"secret_type"` Username sql.NullString `db:"username"` - OauthAccessTokenExpiryTime sql.NullString `db:"oauth_access_token_expiry_time"` - OauthRefreshTokenExpiryTime sql.NullString `db:"oauth_refresh_token_expiry_time"` + OauthAccessTokenExpiryTime *time.Time `db:"oauth_access_token_expiry_time"` + OauthRefreshTokenExpiryTime *time.Time `db:"oauth_refresh_token_expiry_time"` OauthScopes sql.NullString `db:"oauth_scopes"` IntegrationName sql.NullString `db:"integration_name"` } @@ -173,8 +174,8 @@ type SecretDetails struct { Comment sql.NullString SecretType string Username sql.NullString - OauthAccessTokenExpiryTime sql.NullString - OauthRefreshTokenExpiryTime sql.NullString + OauthAccessTokenExpiryTime *time.Time + OauthRefreshTokenExpiryTime *time.Time OauthScopes sql.NullString IntegrationName sql.NullString } diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index d86270636e..ce1070e654 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -1,6 +1,7 @@ package testint import ( + "database/sql" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/stretchr/testify/assert" @@ -9,11 +10,27 @@ import ( "time" ) +const Day = 24 * time.Hour + func TestInt_Secrets(t *testing.T) { client := testClient(t) ctx := testContext(t) + integrationId := testClientHelper().Ids.RandomAccountObjectIdentifier() + refreshTokenExpiryTime := time.Now().Add(Day).Format(time.DateOnly) + + stringDateToSnowflakeTimeFormat := func(inputLayout, date string) *time.Time { + parsedTime, err := time.Parse(inputLayout, date) + require.NoError(t, err) + + loc, err := time.LoadLocation("America/Los_Angeles") + require.NoError(t, err) + + adjustedTime := parsedTime.In(loc) + return &adjustedTime + } + cleanupIntegration := func(t *testing.T, integrationId sdk.AccountObjectIdentifier) func() { return func() { err := client.SecurityIntegrations.Drop(ctx, sdk.NewDropSecurityIntegrationRequest(integrationId).WithIfExists(true)) @@ -21,31 +38,22 @@ func TestInt_Secrets(t *testing.T) { } } - integrationRequest := sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). - WithOauthAllowedScopes([]sdk.AllowedScope{{"foo"}, {"bar"}}) - err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow(ctx, integrationRequest) + err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow( + ctx, + sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). + WithOauthAllowedScopes([]sdk.AllowedScope{{"foo"}, {"bar"}}), + ) require.NoError(t, err) t.Cleanup(cleanupIntegration(t, integrationId)) - cleanupSecret := func(id sdk.SchemaObjectIdentifier) func() { + cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() return func() { err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) require.NoError(t, err) } } - assertSecret := func(t *testing.T, s *sdk.Secret, expectedId sdk.SchemaObjectIdentifier, expectedSecretType, expectedComment string) { - t.Helper() - assert.Equal(t, expectedId.Name(), s.Name) - assert.Equal(t, expectedSecretType, s.SecretType) - assert.Equal(t, expectedComment, s.Comment) - assert.NotEmpty(t, s.CreatedOn) - assert.NotEmpty(t, s.DatabaseName) - assert.NotEmpty(t, s.SchemaName) - assert.NotEmpty(t, s.OwnerRoleType) - assert.NotEmpty(t, s.Owner) - } - createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, scopes []sdk.SecurityIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() @@ -55,7 +63,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) + t.Cleanup(cleanupSecret(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -63,7 +71,7 @@ func TestInt_Secrets(t *testing.T) { return secret, id } - createSecretWithOAuthAuthorizationCodeFlow := func(t *testing.T, refreshToken, refreshTokenExpiryTime string, integrationId sdk.AccountObjectIdentifier, with func(*sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + createSecretWithOAuthAuthorizationCodeFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, refreshToken, refreshTokenExpiryTime string, with func(*sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() request := sdk.NewCreateWithOAuthAuthorizationCodeFlowSecretRequest(id, refreshToken, refreshTokenExpiryTime, integrationId) @@ -72,7 +80,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithOAuthAuthorizationCodeFlow(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) + t.Cleanup(cleanupSecret(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -80,7 +88,7 @@ func TestInt_Secrets(t *testing.T) { return secret, id } - createSecretWithBasicAuthorization := func(t *testing.T, username, password string, with func(*sdk.CreateWithBasicAuthenticationSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + createSecretWithBasicAuthentication := func(t *testing.T, username, password string, with func(*sdk.CreateWithBasicAuthenticationSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password) @@ -89,7 +97,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithBasicAuthentication(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) + t.Cleanup(cleanupSecret(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -97,13 +105,42 @@ func TestInt_Secrets(t *testing.T) { return secret, id } + createSecretWithGenericString := func(t *testing.T, secretString string, with func(options *sdk.CreateWithGenericStringSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + t.Helper() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithGenericStringSecretRequest(id, secretString) + if with != nil { + with(request) + } + err := client.Secrets.CreateWithGenericString(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupSecret(t, id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret, id + } + + assertSecret := func(t *testing.T, s *sdk.Secret, expectedId sdk.SchemaObjectIdentifier, expectedSecretType, expectedComment string) { + t.Helper() + assert.Equal(t, expectedId.Name(), s.Name) + assert.Equal(t, expectedSecretType, s.SecretType) + assert.Equal(t, expectedComment, s.Comment) + assert.NotEmpty(t, s.CreatedOn) + assert.NotEmpty(t, s.DatabaseName) + assert.NotEmpty(t, s.SchemaName) + assert.NotEmpty(t, s.OwnerRoleType) + assert.NotEmpty(t, s.Owner) + } + type secretDetails struct { Name string Comment string SecretType string Username string - OauthAccessTokenExpiryTime time.Time - OauthRefreshTokenExpiryTime time.Time + OauthAccessTokenExpiryTime *time.Time + OauthRefreshTokenExpiryTime *time.Time OauthScopes string IntegrationName string } @@ -113,14 +150,15 @@ func TestInt_Secrets(t *testing.T) { assert.Equal(t, expected.Comment, actual.Comment.String) assert.Equal(t, expected.SecretType, actual.SecretType) assert.Equal(t, expected.Username, actual.Username.String) - assert.Equal(t, expected.OauthAccessTokenExpiryTime.String(), actual.OauthAccessTokenExpiryTime.String) - assert.Equal(t, expected.OauthRefreshTokenExpiryTime.String(), actual.OauthRefreshTokenExpiryTime.String) + assert.Equal(t, expected.OauthAccessTokenExpiryTime, actual.OauthAccessTokenExpiryTime) + assert.Equal(t, expected.OauthRefreshTokenExpiryTime, actual.OauthRefreshTokenExpiryTime) assert.Equal(t, expected.OauthScopes, actual.OauthScopes.String) assert.Equal(t, expected.IntegrationName, actual.IntegrationName.String) } - t.Run("Create secret with OAuth Client Credentials Flow", func(t *testing.T) { + t.Run("Create: secretWithOAuthClientCredentialsFlow", func(t *testing.T) { scopes := []sdk.SecurityIntegrationScope{{"foo"}, {"bar"}} + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, scopes, func(req *sdk.CreateWithOAuthClientCredentialsFlowSecretRequest) { req.WithComment("a"). WithIfNotExists(true) @@ -139,24 +177,39 @@ func TestInt_Secrets(t *testing.T) { assertSecret(t, secret, id, "OAUTH2", "a") }) - // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret should inherit security_integration scopes, but it does not - t.Run("CreateSecretWithOAuthClientCredentialsFlow: No Scopes Specified", func(t *testing.T) { + // It is possible to create secret without specifying both refresh token properties and scopes + // Scopes are not being inherited from the security_integration what is tested further + t.Run("Create: secretWithOAuth - minimal, without token and scopes", func(t *testing.T) { secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{}, nil) - details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "OAUTH2", - IntegrationName: integrationId.Name(), + Name: id.Name(), + SecretType: "OAUTH2", + OauthScopes: "", + OauthAccessTokenExpiryTime: nil, + OauthRefreshTokenExpiryTime: nil, + IntegrationName: integrationId.Name(), }) assertSecret(t, secret, id, "OAUTH2", "") }) - t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { - secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, "foo", "2024-09-20", integrationId, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { + // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret should inherit security_integration scopes, but it does not do so + t.Run("Create: SecretWithOAuthClientCredentialsFlow - No Scopes Specified", func(t *testing.T) { + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{}, nil) + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + securityIntegrationProperties, _ := client.SecurityIntegrations.Describe(ctx, integrationId) + assert.Contains(t, securityIntegrationProperties, sdk.SecurityIntegrationProperty{Name: "OAUTH_ALLOWED_SCOPES", Type: "List", Value: "[foo, bar]", Default: "[]"}) + + assert.NotEqual(t, details.OauthScopes, securityIntegrationProperties) + }) + + t.Run("Create: SecretWithOAuthAuthorizationCodeFlow", func(t *testing.T) { + secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { req.WithComment("a"). WithIfNotExists(true) }) @@ -168,39 +221,17 @@ func TestInt_Secrets(t *testing.T) { Name: id.Name(), SecretType: "OAUTH2", Comment: "a", - OauthRefreshTokenExpiryTime: time.Time{}, //"2024-09-20", + OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, refreshTokenExpiryTime), IntegrationName: integrationId.Name(), }) - assertSecret(t, secret, id, "OAUTH2", "") + assertSecret(t, secret, id, "OAUTH2", "a") }) - /* - //require.EqualError(t, err, "Invalid data/time format string") - t.Run("CreateWithOAuthAuthorizationCodeFlow: Invalid date/time format string", func(t *testing.T) { - secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { - req.WithComment("a"). - WithIfNotExists(true) - }) - - details, err := client.Secrets.Describe(ctx, id) - require.NoError(t, err) - - assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "OAUTH2", - OauthAccessTokenExpiryTime: "foo", - OauthRefreshTokenExpiryTime: "foo", - IntegrationName: integrationId.Name(), - }) - - assertSecret(t, secret, id, "OAUTH2", "") - }) - */ - - t.Run("CreateWithBasicAuthentication", func(t *testing.T) { + t.Run("Create: WithBasicAuthentication", func(t *testing.T) { comment := random.Comment() - secret, id := createSecretWithBasicAuthorization(t, "foo", "foo", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { + + secret, id := createSecretWithBasicAuthentication(t, "foo", "foo", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { req.WithComment(comment). WithIfNotExists(true) }) @@ -217,9 +248,9 @@ func TestInt_Secrets(t *testing.T) { assertSecret(t, secret, id, "PASSWORD", comment) }) - t.Run("CreateWithBasicAuthentication: Empty Username and Password", func(t *testing.T) { + t.Run("Create: WithBasicAuthentication - Empty Username and Password", func(t *testing.T) { comment := random.Comment() - secret, id := createSecretWithBasicAuthorization(t, "", "", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { + secret, id := createSecretWithBasicAuthentication(t, "", "", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { req.WithComment(comment). WithIfNotExists(true) }) @@ -230,32 +261,424 @@ func TestInt_Secrets(t *testing.T) { Name: id.Name(), Comment: comment, SecretType: "PASSWORD", + Username: "", }) assertSecret(t, secret, id, "PASSWORD", comment) }) - t.Run("CreateWithGenericString", func(t *testing.T) { - // TODO: fill me + t.Run("Create: WithGenericString", func(t *testing.T) { + comment := random.Comment() + secret, id := createSecretWithGenericString(t, "foo", func(req *sdk.CreateWithGenericStringSecretRequest) { + req.WithComment(comment). + WithIfNotExists(true) + }) + + assertSecret(t, secret, id, "GENERIC_STRING", comment) + }) + + t.Run("Create: WithGenericString - empty secret_string", func(t *testing.T) { + secret, id := createSecretWithGenericString(t, "", nil) + require.NoError(t, err) + + assertSecret(t, secret, id, "GENERIC_STRING", "") + }) + + t.Run("Alter: SecretWithOAuthClientCredentials", func(t *testing.T) { + comment := random.Comment() + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForOAuthClientCredentialsFlow( + *sdk.NewSetForOAuthClientCredentialsFlowRequest( + []sdk.SecurityIntegrationScope{{"foo"}, {"bar"}}, + ), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + Comment: comment, + OauthScopes: "[foo, bar]", + IntegrationName: integrationId.Name(), + }) + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) + }) + + t.Run("Alter: SecretWithOAuthAuthorizationCode", func(t *testing.T) { + comment := random.Comment() + alteredRefreshTokenExpiryTime := time.Now().Add(4 * Day).Format(time.DateOnly) + + _, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForOAuthAuthorizationFlow( + *sdk.NewSetForOAuthAuthorizationFlowRequest(). + WithOauthRefreshToken("bar"). + WithOauthRefreshTokenExpiryTime(alteredRefreshTokenExpiryTime), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + Comment: comment, + OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, alteredRefreshTokenExpiryTime), + IntegrationName: integrationId.Name(), + }) + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) + }) + + t.Run("Alter: SecretWithBasicAuthorization", func(t *testing.T) { + comment := random.Comment() + + _, id := createSecretWithBasicAuthentication(t, "foo", "foo", nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForBasicAuthentication( + *sdk.NewSetForBasicAuthenticationRequest(). + WithUsername("bar"). + WithPassword("bar"), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + // Cannot check password since show and describe on secret do not have access to password property + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "PASSWORD", + Comment: comment, + Username: "bar", + }) + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) }) - t.Run("Alter", func(t *testing.T) { - // TODO: fill me + t.Run("Alter: SecretWithGenericString", func(t *testing.T) { + comment := random.Comment() + _, id := createSecretWithGenericString(t, "foo", nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForGenericString( + *sdk.NewSetForGenericStringRequest(). + WithSecretString("bar"), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + /* + // Cannot check secret_string since show and describe on secret do not have access to secret_string property + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "PASSWORD", + Comment: comment, + }) + */ + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) }) t.Run("Drop", func(t *testing.T) { - // TODO: fill me + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NotNil(t, secret) + require.NoError(t, err) + + err = client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id)) + require.NoError(t, err) + + secret, err = client.Secrets.ShowByID(ctx, id) + require.Nil(t, secret) + require.Error(t, err) + }) + + t.Run("Drop: non-existing", func(t *testing.T) { + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id)) + assert.ErrorIs(t, err, sdk.ErrObjectNotExistOrAuthorized) }) t.Run("Show", func(t *testing.T) { - // TODO: fill me + secretOAuthClientCredentials, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) + secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest()) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + }) + + t.Run("Show: SecretWithOAuthClientCredentialsFlow with Like", func(t *testing.T) { + secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"bar"}}, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithOAuthAuthorization with Like", func(t *testing.T) { + secret1, id1 := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_1", refreshTokenExpiryTime, nil) + secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithBasicAuthentication with Like", func(t *testing.T) { + secret1, id1 := createSecretWithBasicAuthentication(t, "foo_1", "bar_1", nil) + secret2, _ := createSecretWithBasicAuthentication(t, "foo_2", "bar_2", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithGenericString with Like", func(t *testing.T) { + secret1, id1 := createSecretWithGenericString(t, "foo_1", nil) + secret2, _ := createSecretWithGenericString(t, "foo_2", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithOAuthClientCredentialsFlow with In", func(t *testing.T) { + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + }) + + t.Run("Show: SecretWithOAuthAuthorizationCodeFlow with In", func(t *testing.T) { + secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + }) + + t.Run("Show: with In", func(t *testing.T) { + secretOAuthClientCredentials, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) + secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + }) + + t.Run("Show: SecretWithGenericString with In", func(t *testing.T) { + secret, id := createSecretWithGenericString(t, "foo", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) }) t.Run("ShowByID", func(t *testing.T) { - // TODO: fill me + _, id := createSecretWithGenericString(t, "foo", nil) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + assertSecret(t, secret, id, "GENERIC_STRING", "") }) t.Run("Describe", func(t *testing.T) { - // TODO: fill me + _, id := createSecretWithGenericString(t, "foo", func(req *sdk.CreateWithGenericStringSecretRequest) { + req.WithComment("Lorem ipsum") + }) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + Comment: "Lorem ipsum", + SecretType: "GENERIC_STRING", + }) + }) +} + +func TestInt_SecretsShowWithIn(t *testing.T) { + client := testClient(t) + ctx := testContext(t) + + cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + return func() { + err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) + require.NoError(t, err) + } + } + + createSecretWithGenericString := func(t *testing.T, id sdk.SchemaObjectIdentifier, secretString string) *sdk.Secret { + t.Helper() + request := sdk.NewCreateWithGenericStringSecretRequest(id, secretString) + err := client.Secrets.CreateWithGenericString(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupSecret(t, id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret + } + + t.Run("Show with In - same id in different schemas", func(t *testing.T) { + schema, schemaCleanup := testClientHelper().Schema.CreateSchema(t) + t.Cleanup(schemaCleanup) + + id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + id2 := testClientHelper().Ids.NewSchemaObjectIdentifierInSchema(id1.Name(), schema.ID()) + + secret1 := createSecretWithGenericString(t, id1, "foo") + secret2 := createSecretWithGenericString(t, id2, "bar") + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id1.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id1.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.Contains(t, returnedSecrets, *secret2) }) + } From 0e9cf948be2be755b8992eeb1923f28649c36bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Thu, 19 Sep 2024 11:20:08 +0200 Subject: [PATCH 17/34] linter --- pkg/acceptance/helpers/secret_client.go | 3 ++- pkg/sdk/secrets_impl_gen.go | 10 ---------- pkg/sdk/testint/secrets_gen_integration_test.go | 6 +++--- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/pkg/acceptance/helpers/secret_client.go b/pkg/acceptance/helpers/secret_client.go index aa98ceafb1..ab980051c3 100644 --- a/pkg/acceptance/helpers/secret_client.go +++ b/pkg/acceptance/helpers/secret_client.go @@ -3,10 +3,11 @@ package helpers import ( "context" "errors" + "testing" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" ) type SecretClient struct { diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index 1386955543..7d548240ad 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -133,47 +133,37 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { } if r.Set.SetForOAuthClientCredentialsFlow != nil { - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{ OauthScopes: r.Set.SetForOAuthClientCredentialsFlow.OauthScopes, } - } if r.Set.SetForOAuthAuthorizationFlow != nil { - opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ OauthRefreshToken: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshToken, OauthRefreshTokenExpiryTime: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshTokenExpiryTime, } - } if r.Set.SetForBasicAuthentication != nil { - opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{ Username: r.Set.SetForBasicAuthentication.Username, Password: r.Set.SetForBasicAuthentication.Password, } - } if r.Set.SetForGenericString != nil { - opts.Set.SetForGenericString = &SetForGenericString{ SecretString: r.Set.SetForGenericString.SecretString, } - } } if r.Unset != nil { - opts.Unset = &SecretUnset{ Comment: r.Unset.Comment, } - } return opts diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index ce1070e654..4ee38140d0 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -2,12 +2,13 @@ package testint import ( "database/sql" + "testing" + "time" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" - "time" ) const Day = 24 * time.Hour @@ -680,5 +681,4 @@ func TestInt_SecretsShowWithIn(t *testing.T) { require.Contains(t, returnedSecrets, *secret1) require.Contains(t, returnedSecrets, *secret2) }) - } From deadc651019c0f6016ed602914993184c4f1019a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Thu, 19 Sep 2024 11:48:05 +0200 Subject: [PATCH 18/34] linting --- pkg/sdk/secrets_impl_gen.go | 2 - .../testint/secrets_gen_integration_test.go | 46 +++++++++---------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index 7d548240ad..3321b27380 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -127,7 +127,6 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { } if r.Set != nil { - opts.Set = &SecretSet{ Comment: r.Set.Comment, } @@ -157,7 +156,6 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { SecretString: r.Set.SetForGenericString.SecretString, } } - } if r.Unset != nil { diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 4ee38140d0..7b7a9d9618 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -33,6 +33,7 @@ func TestInt_Secrets(t *testing.T) { } cleanupIntegration := func(t *testing.T, integrationId sdk.AccountObjectIdentifier) func() { + t.Helper() return func() { err := client.SecurityIntegrations.Drop(ctx, sdk.NewDropSecurityIntegrationRequest(integrationId).WithIfExists(true)) require.NoError(t, err) @@ -42,7 +43,7 @@ func TestInt_Secrets(t *testing.T) { err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow( ctx, sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). - WithOauthAllowedScopes([]sdk.AllowedScope{{"foo"}, {"bar"}}), + WithOauthAllowedScopes([]sdk.AllowedScope{{Scope: "foo"}, {Scope: "bar"}}), ) require.NoError(t, err) t.Cleanup(cleanupIntegration(t, integrationId)) @@ -158,7 +159,7 @@ func TestInt_Secrets(t *testing.T) { } t.Run("Create: secretWithOAuthClientCredentialsFlow", func(t *testing.T) { - scopes := []sdk.SecurityIntegrationScope{{"foo"}, {"bar"}} + scopes := []sdk.SecurityIntegrationScope{{Scope: "foo"}, {Scope: "bar"}} secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, scopes, func(req *sdk.CreateWithOAuthClientCredentialsFlowSecretRequest) { req.WithComment("a"). @@ -287,14 +288,14 @@ func TestInt_Secrets(t *testing.T) { t.Run("Alter: SecretWithOAuthClientCredentials", func(t *testing.T) { comment := random.Comment() - _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) setRequest := sdk.NewAlterSecretRequest(id). WithSet( *sdk.NewSecretSetRequest(). WithComment(comment). WithSetForOAuthClientCredentialsFlow( *sdk.NewSetForOAuthClientCredentialsFlowRequest( - []sdk.SecurityIntegrationScope{{"foo"}, {"bar"}}, + []sdk.SecurityIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}, ), ), ) @@ -323,7 +324,7 @@ func TestInt_Secrets(t *testing.T) { details, err = client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{"", false}) + assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) }) t.Run("Alter: SecretWithOAuthAuthorizationCode", func(t *testing.T) { @@ -366,7 +367,7 @@ func TestInt_Secrets(t *testing.T) { details, err = client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{"", false}) + assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) }) t.Run("Alter: SecretWithBasicAuthorization", func(t *testing.T) { @@ -408,7 +409,7 @@ func TestInt_Secrets(t *testing.T) { details, err = client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{"", false}) + assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) }) t.Run("Alter: SecretWithGenericString", func(t *testing.T) { @@ -426,16 +427,13 @@ func TestInt_Secrets(t *testing.T) { err := client.Secrets.Alter(ctx, setRequest) require.NoError(t, err) - details, err := client.Secrets.Describe(ctx, id) - require.NoError(t, err) - + // Cannot check secret_string since show and describe on secret do not have access to secret_string property /* - // Cannot check secret_string since show and describe on secret do not have access to secret_string property - assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "PASSWORD", - Comment: comment, - }) + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "PASSWORD", + Comment: comment, + }) */ unsetRequest := sdk.NewAlterSecretRequest(id). @@ -446,14 +444,14 @@ func TestInt_Secrets(t *testing.T) { err = client.Secrets.Alter(ctx, unsetRequest) require.NoError(t, err) - details, err = client.Secrets.Describe(ctx, id) + details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{"", false}) + assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) }) t.Run("Drop", func(t *testing.T) { - _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) secret, err := client.Secrets.ShowByID(ctx, id) require.NotNil(t, secret) @@ -475,7 +473,7 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show", func(t *testing.T) { - secretOAuthClientCredentials, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secretOAuthClientCredentials, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) @@ -489,8 +487,8 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with Like", func(t *testing.T) { - secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) - secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"bar"}}, nil) + secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) + secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "bar"}}, nil) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ Pattern: sdk.Pointer(id1.Name()), @@ -537,7 +535,7 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with In", func(t *testing.T) { - secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) require.NoError(t, err) @@ -569,7 +567,7 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: with In", func(t *testing.T) { - secretOAuthClientCredentials, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secretOAuthClientCredentials, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) From 235fbe51ccfe942b624ba05ab38d8164bf7a38bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Thu, 19 Sep 2024 11:50:26 +0200 Subject: [PATCH 19/34] removing comment --- pkg/sdk/testint/secrets_gen_integration_test.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 7b7a9d9618..538590a28e 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -390,7 +390,7 @@ func TestInt_Secrets(t *testing.T) { details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) - // Cannot check password since show and describe on secret do not have access to password property + // Cannot check password property since show and describe on secret do not have access to it assertSecretDetails(details, secretDetails{ Name: id.Name(), SecretType: "PASSWORD", @@ -427,15 +427,6 @@ func TestInt_Secrets(t *testing.T) { err := client.Secrets.Alter(ctx, setRequest) require.NoError(t, err) - // Cannot check secret_string since show and describe on secret do not have access to secret_string property - /* - assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "PASSWORD", - Comment: comment, - }) - */ - unsetRequest := sdk.NewAlterSecretRequest(id). WithUnset( *sdk.NewSecretUnsetRequest(). From 73eeb634e4c8b3921606be6dcf7b22f4a5160b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Fri, 20 Sep 2024 14:27:21 +0200 Subject: [PATCH 20/34] mid review commit before generating assertions --- pkg/sdk/secrets_def.go | 20 +++--- pkg/sdk/secrets_gen.go | 12 ++-- pkg/sdk/secrets_gen_test.go | 6 ++ .../testint/secrets_gen_integration_test.go | 65 ++++++++++--------- 4 files changed, 60 insertions(+), 43 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index ddd1fa95fd..2b173f2cd3 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -4,7 +4,7 @@ import g "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/gen //go:generate go run ./poc/main.go -var secretsSecurityIntegrationScopeDef = g.NewQueryStruct("SecurityIntegrationScope"). +var secretsApiIntegrationScopeDef = g.NewQueryStruct("ApiIntegrationScope"). Text("Scope", g.KeywordOptions().SingleQuotes().Required()) var secretDbRow = g.DbStruct("secretDBRow"). @@ -62,7 +62,7 @@ var secretSet = g.NewQueryStruct("SecretSet"). OptionalQueryStructField( "SetForOAuthClientCredentialsFlow", g.NewQueryStruct("SetForOAuthClientCredentialsFlow"). - ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses().Required()), + ListAssignment("OAUTH_SCOPES", "ApiIntegrationScope", g.ParameterOptions().Parentheses().Required()), g.KeywordOptions(), ). OptionalQueryStructField( @@ -85,7 +85,7 @@ var secretSet = g.NewQueryStruct("SecretSet"). OptionalTextAssignment("SECRET_STRING", g.ParameterOptions().SingleQuotes()), g.KeywordOptions(), ). - WithValidation(g.ExactlyOneValueSet, "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString") + WithValidation(g.ConflictingFields, "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString") // UNSET doest work, need to use "SET COMMENT = NULL" var secretUnset = g.NewQueryStruct("SecretUnset"). @@ -105,12 +105,12 @@ var SecretsDef = g.NewInterface( IfNotExists(). Name(). PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). - Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION").Required()). - ListAssignment("OAUTH_SCOPES", "SecurityIntegrationScope", g.ParameterOptions().Parentheses().Required()). + Identifier("ApiIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). + ListAssignment("OAUTH_SCOPES", "ApiIntegrationScope", g.ParameterOptions().Parentheses().Required()). OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), - secretsSecurityIntegrationScopeDef, + secretsApiIntegrationScopeDef, ).CustomOperation( "CreateWithOAuthAuthorizationCodeFlow", "https://docs.snowflake.com/en/sql-reference/sql/create-secret", @@ -123,11 +123,11 @@ var SecretsDef = g.NewInterface( PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). TextAssignment("OAUTH_REFRESH_TOKEN", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). TextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). - Identifier("SecurityIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). + Identifier("ApiIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), - secretsSecurityIntegrationScopeDef, + secretsApiIntegrationScopeDef, ).CustomOperation( "CreateWithBasicAuthentication", "https://docs.snowflake.com/en/sql-reference/sql/create-secret", @@ -184,14 +184,14 @@ var SecretsDef = g.NewInterface( Name(). WithValidation(g.ValidIdentifier, "name"), ).ShowOperation( - "https://docs.snowflake.com/en/sql-reference/sql/show-secret", + "https://docs.snowflake.com/en/sql-reference/sql/show-secrets", secretDbRow, secret, g.NewQueryStruct("ShowSecret"). Show(). SQL("SECRETS"). OptionalLike(). - OptionalIn(), + OptionalExtendedIn(), ).ShowByIdOperation(). DescribeOperation( g.DescriptionMappingKindSingleValue, diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index b90ac53ea3..d1bf5d9132 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -145,6 +145,10 @@ type Secret struct { OwnerRoleType string } +func (s *Secret) ID() SchemaObjectIdentifier { + return NewSchemaObjectIdentifier(s.DatabaseName, s.SchemaName, s.Name) +} + // DescribeSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/desc-secret. type DescribeSecretOptions struct { describe bool `ddl:"static" sql:"DESCRIBE"` @@ -171,11 +175,11 @@ type SecretDetails struct { SchemaName string DatabaseName string Owner string - Comment sql.NullString + Comment *string SecretType string - Username sql.NullString + Username *string OauthAccessTokenExpiryTime *time.Time OauthRefreshTokenExpiryTime *time.Time - OauthScopes sql.NullString - IntegrationName sql.NullString + OauthScopes *string + IntegrationName *string } diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 692737fe14..27f0c50036 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -218,6 +218,12 @@ func TestSecrets_Alter(t *testing.T) { assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' USERNAME = 'foo' PASSWORD = 'bar'", id.FullyQualifiedName()) }) + t.Run("alter: set comment only", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test'", id.FullyQualifiedName()) + }) + t.Run("alter: set options for Generic string", func(t *testing.T) { opts := setOpts() opts.Set.Comment = String("test") diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 538590a28e..bd50d292e3 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -11,26 +11,13 @@ import ( "github.com/stretchr/testify/require" ) -const Day = 24 * time.Hour - func TestInt_Secrets(t *testing.T) { client := testClient(t) ctx := testContext(t) integrationId := testClientHelper().Ids.RandomAccountObjectIdentifier() - refreshTokenExpiryTime := time.Now().Add(Day).Format(time.DateOnly) - - stringDateToSnowflakeTimeFormat := func(inputLayout, date string) *time.Time { - parsedTime, err := time.Parse(inputLayout, date) - require.NoError(t, err) - - loc, err := time.LoadLocation("America/Los_Angeles") - require.NoError(t, err) - - adjustedTime := parsedTime.In(loc) - return &adjustedTime - } + refreshTokenExpiryTime := time.Now().Add(24 * time.Hour).Format(time.DateOnly) cleanupIntegration := func(t *testing.T, integrationId sdk.AccountObjectIdentifier) func() { t.Helper() @@ -48,14 +35,34 @@ func TestInt_Secrets(t *testing.T) { require.NoError(t, err) t.Cleanup(cleanupIntegration(t, integrationId)) - cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { - t.Helper() - return func() { - err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) - require.NoError(t, err) - } + /* + apiIntegration, dropApiIntegration := testClientHelper().ApiIntegration.CreateApiIntegration(t) + sdk.NewAlterApiIntegrationRequest(apiIntegration.ID()). + WithSet(sdk.NewApiIntegrationSetRequest()) + t.Cleanup(dropApiIntegration) + */ + + stringDateToSnowflakeTimeFormat := func(inputLayout, date string) *time.Time { + parsedTime, err := time.Parse(inputLayout, date) + require.NoError(t, err) + + loc, err := time.LoadLocation("America/Los_Angeles") + require.NoError(t, err) + + adjustedTime := parsedTime.In(loc) + return &adjustedTime } + /* + cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + return func() { + err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) + require.NoError(t, err) + } + } + */ + createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, scopes []sdk.SecurityIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() @@ -65,7 +72,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(t, id)) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -82,7 +89,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithOAuthAuthorizationCodeFlow(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(t, id)) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -99,7 +106,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithBasicAuthentication(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(t, id)) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -116,7 +123,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithGenericString(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(t, id)) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -149,13 +156,13 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails := func(actual *sdk.SecretDetails, expected secretDetails) { assert.Equal(t, expected.Name, actual.Name) - assert.Equal(t, expected.Comment, actual.Comment.String) + assert.Equal(t, expected.Comment, actual.Comment) assert.Equal(t, expected.SecretType, actual.SecretType) - assert.Equal(t, expected.Username, actual.Username.String) + assert.Equal(t, expected.Username, actual.Username) assert.Equal(t, expected.OauthAccessTokenExpiryTime, actual.OauthAccessTokenExpiryTime) assert.Equal(t, expected.OauthRefreshTokenExpiryTime, actual.OauthRefreshTokenExpiryTime) - assert.Equal(t, expected.OauthScopes, actual.OauthScopes.String) - assert.Equal(t, expected.IntegrationName, actual.IntegrationName.String) + assert.Equal(t, expected.OauthScopes, actual.OauthScopes) + assert.Equal(t, expected.IntegrationName, actual.IntegrationName) } t.Run("Create: secretWithOAuthClientCredentialsFlow", func(t *testing.T) { @@ -329,7 +336,7 @@ func TestInt_Secrets(t *testing.T) { t.Run("Alter: SecretWithOAuthAuthorizationCode", func(t *testing.T) { comment := random.Comment() - alteredRefreshTokenExpiryTime := time.Now().Add(4 * Day).Format(time.DateOnly) + alteredRefreshTokenExpiryTime := time.Now().Add(4 * 24 * time.Hour).Format(time.DateOnly) _, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) setRequest := sdk.NewAlterSecretRequest(id). From bd0b64fe1f27254e33bec37ff926a16e08587023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 23 Sep 2024 13:49:50 +0200 Subject: [PATCH 21/34] rebase conflict resolved --- .../assert/objectassert/gen/sdk_object_def.go | 5 + .../objectassert/secret_snowflake_gen.go | 136 ++++++ pkg/acceptance/helpers/secret_client.go | 21 +- pkg/sdk/secrets_def.go | 26 +- pkg/sdk/secrets_dto_builders_gen.go | 14 +- pkg/sdk/secrets_dto_gen.go | 18 +- pkg/sdk/secrets_gen.go | 50 ++- pkg/sdk/secrets_gen_test.go | 24 +- pkg/sdk/secrets_impl_gen.go | 62 ++- pkg/sdk/secrets_validations_gen.go | 4 +- .../testint/secrets_gen_integration_test.go | 400 ++++++++++-------- 11 files changed, 499 insertions(+), 261 deletions(-) create mode 100644 pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go diff --git a/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go b/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go index 9fe810dfbe..e3480374f2 100644 --- a/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go +++ b/pkg/acceptance/bettertestspoc/assert/objectassert/gen/sdk_object_def.go @@ -62,6 +62,11 @@ var allStructs = []SdkObjectDef{ ObjectType: sdk.ObjectTypeTask, ObjectStruct: sdk.Task{}, }, + { + IdType: "sdk.SchemaObjectIdentifier", + ObjectType: sdk.ObjectTypeSecret, + ObjectStruct: sdk.Secret{}, + }, } func GetSdkObjectDetails() []genhelpers.SdkObjectDetails { diff --git a/pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go b/pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go new file mode 100644 index 0000000000..193e09b18e --- /dev/null +++ b/pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go @@ -0,0 +1,136 @@ +// Code generated by assertions generator; DO NOT EDIT. + +package objectassert + +import ( + "fmt" + "testing" + + acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" +) + +type SecretAssert struct { + *assert.SnowflakeObjectAssert[sdk.Secret, sdk.SchemaObjectIdentifier] +} + +func Secret(t *testing.T, id sdk.SchemaObjectIdentifier) *SecretAssert { + t.Helper() + return &SecretAssert{ + assert.NewSnowflakeObjectAssertWithProvider(sdk.ObjectTypeSecret, id, acc.TestClient().Secret.Show), + } +} + +func SecretFromObject(t *testing.T, secret *sdk.Secret) *SecretAssert { + t.Helper() + return &SecretAssert{ + assert.NewSnowflakeObjectAssertWithObject(sdk.ObjectTypeSecret, secret.ID(), secret), + } +} + +func (s *SecretAssert) HasCreatedOn(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.CreatedOn != expected { + return fmt.Errorf("expected created on: %v; got: %v", expected, o.CreatedOn) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasName(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.Name != expected { + return fmt.Errorf("expected name: %v; got: %v", expected, o.Name) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasSchemaName(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.SchemaName != expected { + return fmt.Errorf("expected schema name: %v; got: %v", expected, o.SchemaName) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasDatabaseName(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.DatabaseName != expected { + return fmt.Errorf("expected database name: %v; got: %v", expected, o.DatabaseName) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasOwner(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.Owner != expected { + return fmt.Errorf("expected owner: %v; got: %v", expected, o.Owner) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasComment(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.Comment == nil { + return fmt.Errorf("expected comment to have value; got: nil") + } + if *o.Comment != expected { + return fmt.Errorf("expected comment: %v; got: %v", expected, *o.Comment) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasSecretType(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.SecretType != expected { + return fmt.Errorf("expected secret type: %v; got: %v", expected, o.SecretType) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasOauthScopes(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.OauthScopes == nil { + return fmt.Errorf("expected oauth scopes to have value; got: nil") + } + if *o.OauthScopes != expected { + return fmt.Errorf("expected oauth scopes: %v; got: %v", expected, *o.OauthScopes) + } + return nil + }) + return s +} + +func (s *SecretAssert) HasOwnerRoleType(expected string) *SecretAssert { + s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { + t.Helper() + if o.OwnerRoleType != expected { + return fmt.Errorf("expected owner role type: %v; got: %v", expected, o.OwnerRoleType) + } + return nil + }) + return s +} diff --git a/pkg/acceptance/helpers/secret_client.go b/pkg/acceptance/helpers/secret_client.go index ab980051c3..314f6248b5 100644 --- a/pkg/acceptance/helpers/secret_client.go +++ b/pkg/acceptance/helpers/secret_client.go @@ -2,7 +2,6 @@ package helpers import ( "context" - "errors" "testing" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -26,7 +25,7 @@ func (c *SecretClient) client() sdk.Secrets { return c.context.client.Secrets } -func (c *SecretClient) CreateSecreteWithBasicFlow(t *testing.T, id sdk.SchemaObjectIdentifier, username, password string) (*sdk.Secret, func()) { +func (c *SecretClient) CreateWithBasicFlow(t *testing.T, id sdk.SchemaObjectIdentifier, username, password string) (*sdk.Secret, func()) { t.Helper() ctx := context.Background() request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password) @@ -37,20 +36,22 @@ func (c *SecretClient) CreateSecreteWithBasicFlow(t *testing.T, id sdk.SchemaObj secret, err := c.client().ShowByID(ctx, id) require.NoError(t, err) - return secret, c.CleanupSecretFunc(t, id) + return secret, c.DropFunc(t, id) } -func (c *SecretClient) CleanupSecretFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { +func (c *SecretClient) DropFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { t.Helper() ctx := context.Background() return func() { - _, err := c.client().ShowByID(ctx, id) - if errors.Is(err, sdk.ErrObjectNotExistOrAuthorized) { - return - } - - err = c.client().Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) + err := c.client().Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) assert.NoError(t, err) } } + +func (c *SecretClient) Show(t *testing.T, id sdk.SchemaObjectIdentifier) (*sdk.Secret, error) { + t.Helper() + ctx := context.Background() + + return c.client().ShowByID(ctx, id) +} diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 2b173f2cd3..23f51352d8 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -8,7 +8,7 @@ var secretsApiIntegrationScopeDef = g.NewQueryStruct("ApiIntegrationScope"). Text("Scope", g.KeywordOptions().SingleQuotes().Required()) var secretDbRow = g.DbStruct("secretDBRow"). - Field("created_on", "string"). + Field("created_on", "time.Time"). Field("name", "string"). Field("schema_name", "string"). Field("database_name", "string"). @@ -19,18 +19,18 @@ var secretDbRow = g.DbStruct("secretDBRow"). Field("owner_role_type", "string") var secret = g.PlainStruct("Secret"). - Field("CreatedOn", "string"). + Field("CreatedOn", "time.Time"). Field("Name", "string"). Field("SchemaName", "string"). Field("DatabaseName", "string"). Field("Owner", "string"). - Field("Comment", "string"). + Field("Comment", "*string"). Field("SecretType", "string"). - Field("OauthScopes", "sql.NullString"). + Field("OauthScopes", "[]string"). Field("OwnerRoleType", "string") var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). - Field("created_on", "string"). + Field("created_on", "time.Time"). Field("name", "string"). Field("schema_name", "string"). Field("database_name", "string"). @@ -38,24 +38,24 @@ var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). Field("comment", "sql.NullString"). Field("secret_type", "string"). Field("username", "sql.NullString"). - Time("oauth_access_token_expiry_time"). - Time("oauth_refresh_token_expiry_time"). + Field("oauth_access_token_expiry_time", "*time.Time"). + Field("oauth_refresh_token_expiry_time", "*time.Time"). Field("oauth_scopes", "sql.NullString"). Field("integration_name", "sql.NullString") var secretDetails = g.PlainStruct("SecretDetails"). - Field("CreatedOn", "string"). + Field("CreatedOn", "time.Time"). Field("Name", "string"). Field("SchemaName", "string"). Field("DatabaseName", "string"). Field("Owner", "string"). - Field("Comment", "sql.NullString"). + Field("Comment", "*string"). Field("SecretType", "string"). - Field("Username", "sql.NullString"). + Field("Username", "*string"). Field("OauthAccessTokenExpiryTime", "*time.Time"). Field("OauthRefreshTokenExpiryTime", "*time.Time"). - Field("OauthScopes", "sql.NullString"). - Field("IntegrationName", "sql.NullString") + Field("OauthScopes", "*string"). + Field("IntegrationName", "*string") var secretSet = g.NewQueryStruct("SecretSet"). OptionalComment(). @@ -137,7 +137,7 @@ var SecretsDef = g.NewInterface( SQL("SECRET"). IfNotExists(). Name(). - PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = PASSWORD")). + PredefinedQueryStructField("secretType", "string", g.StaticOptions().SQL("TYPE = PASSWORD")). TextAssignment("USERNAME", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). TextAssignment("PASSWORD", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). OptionalComment(). diff --git a/pkg/sdk/secrets_dto_builders_gen.go b/pkg/sdk/secrets_dto_builders_gen.go index faf3a01bf9..9faeabb35a 100644 --- a/pkg/sdk/secrets_dto_builders_gen.go +++ b/pkg/sdk/secrets_dto_builders_gen.go @@ -6,12 +6,12 @@ import () func NewCreateWithOAuthClientCredentialsFlowSecretRequest( name SchemaObjectIdentifier, - SecurityIntegration AccountObjectIdentifier, - OauthScopes []SecurityIntegrationScope, + ApiIntegration AccountObjectIdentifier, + OauthScopes []ApiIntegrationScope, ) *CreateWithOAuthClientCredentialsFlowSecretRequest { s := CreateWithOAuthClientCredentialsFlowSecretRequest{} s.name = name - s.SecurityIntegration = SecurityIntegration + s.ApiIntegration = ApiIntegration s.OauthScopes = OauthScopes return &s } @@ -35,13 +35,13 @@ func NewCreateWithOAuthAuthorizationCodeFlowSecretRequest( name SchemaObjectIdentifier, OauthRefreshToken string, OauthRefreshTokenExpiryTime string, - SecurityIntegration AccountObjectIdentifier, + ApiIntegration AccountObjectIdentifier, ) *CreateWithOAuthAuthorizationCodeFlowSecretRequest { s := CreateWithOAuthAuthorizationCodeFlowSecretRequest{} s.name = name s.OauthRefreshToken = OauthRefreshToken s.OauthRefreshTokenExpiryTime = OauthRefreshTokenExpiryTime - s.SecurityIntegration = SecurityIntegration + s.ApiIntegration = ApiIntegration return &s } @@ -165,7 +165,7 @@ func (s *SecretSetRequest) WithSetForGenericString(SetForGenericString SetForGen } func NewSetForOAuthClientCredentialsFlowRequest( - OauthScopes []SecurityIntegrationScope, + OauthScopes []ApiIntegrationScope, ) *SetForOAuthClientCredentialsFlowRequest { s := SetForOAuthClientCredentialsFlowRequest{} s.OauthScopes = OauthScopes @@ -240,7 +240,7 @@ func (s *ShowSecretRequest) WithLike(Like Like) *ShowSecretRequest { return s } -func (s *ShowSecretRequest) WithIn(In In) *ShowSecretRequest { +func (s *ShowSecretRequest) WithIn(In ExtendedIn) *ShowSecretRequest { s.In = &In return s } diff --git a/pkg/sdk/secrets_dto_gen.go b/pkg/sdk/secrets_dto_gen.go index 36d3f1ef22..3eec952bb4 100644 --- a/pkg/sdk/secrets_dto_gen.go +++ b/pkg/sdk/secrets_dto_gen.go @@ -14,12 +14,12 @@ var ( ) type CreateWithOAuthClientCredentialsFlowSecretRequest struct { - OrReplace *bool - IfNotExists *bool - name SchemaObjectIdentifier // required - SecurityIntegration AccountObjectIdentifier // required - OauthScopes []SecurityIntegrationScope // required - Comment *string + OrReplace *bool + IfNotExists *bool + name SchemaObjectIdentifier // required + ApiIntegration AccountObjectIdentifier // required + OauthScopes []ApiIntegrationScope // required + Comment *string } type CreateWithOAuthAuthorizationCodeFlowSecretRequest struct { @@ -28,7 +28,7 @@ type CreateWithOAuthAuthorizationCodeFlowSecretRequest struct { name SchemaObjectIdentifier // required OauthRefreshToken string // required OauthRefreshTokenExpiryTime string // required - SecurityIntegration AccountObjectIdentifier // required + ApiIntegration AccountObjectIdentifier // required Comment *string } @@ -65,7 +65,7 @@ type SecretSetRequest struct { } type SetForOAuthClientCredentialsFlowRequest struct { - OauthScopes []SecurityIntegrationScope // required + OauthScopes []ApiIntegrationScope // required } type SetForOAuthAuthorizationFlowRequest struct { @@ -93,7 +93,7 @@ type DropSecretRequest struct { type ShowSecretRequest struct { Like *Like - In *In + In *ExtendedIn } type DescribeSecretRequest struct { diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index d1bf5d9132..7e35b008bc 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -20,17 +20,17 @@ type Secrets interface { // CreateWithOAuthClientCredentialsFlowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-secret. type CreateWithOAuthClientCredentialsFlowSecretOptions struct { - create bool `ddl:"static" sql:"CREATE"` - OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` - secret bool `ddl:"static" sql:"SECRET"` - IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` - name SchemaObjectIdentifier `ddl:"identifier"` - Type string `ddl:"static" sql:"TYPE = OAUTH2"` - SecurityIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` - OauthScopes []SecurityIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` - Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` -} -type SecurityIntegrationScope struct { + create bool `ddl:"static" sql:"CREATE"` + OrReplace *bool `ddl:"keyword" sql:"OR REPLACE"` + secret bool `ddl:"static" sql:"SECRET"` + IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` + name SchemaObjectIdentifier `ddl:"identifier"` + secretType string `ddl:"static" sql:"TYPE = OAUTH2"` + ApiIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` + OauthScopes []ApiIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` + Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` +} +type ApiIntegrationScope struct { Scope string `ddl:"keyword,single_quotes"` } @@ -44,7 +44,7 @@ type CreateWithOAuthAuthorizationCodeFlowSecretOptions struct { Type string `ddl:"static" sql:"TYPE = OAUTH2"` OauthRefreshToken string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` OauthRefreshTokenExpiryTime string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN_EXPIRY_TIME"` - SecurityIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` + ApiIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` } @@ -90,7 +90,7 @@ type SecretSet struct { SetForGenericString *SetForGenericString `ddl:"keyword"` } type SetForOAuthClientCredentialsFlow struct { - OauthScopes []SecurityIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` + OauthScopes []ApiIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` } type SetForOAuthAuthorizationFlow struct { OauthRefreshToken *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` @@ -115,15 +115,15 @@ type DropSecretOptions struct { name SchemaObjectIdentifier `ddl:"identifier"` } -// ShowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/show-secret. +// ShowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/show-secrets. type ShowSecretOptions struct { - show bool `ddl:"static" sql:"SHOW"` - secrets bool `ddl:"static" sql:"SECRETS"` - Like *Like `ddl:"keyword" sql:"LIKE"` - In *In `ddl:"keyword" sql:"IN"` + show bool `ddl:"static" sql:"SHOW"` + secrets bool `ddl:"static" sql:"SECRETS"` + Like *Like `ddl:"keyword" sql:"LIKE"` + In *ExtendedIn `ddl:"keyword" sql:"IN"` } type secretDBRow struct { - CreatedOn string `db:"created_on"` + CreatedOn time.Time `db:"created_on"` Name string `db:"name"` SchemaName string `db:"schema_name"` DatabaseName string `db:"database_name"` @@ -134,14 +134,14 @@ type secretDBRow struct { OwnerRoleType string `db:"owner_role_type"` } type Secret struct { - CreatedOn string + CreatedOn time.Time Name string SchemaName string DatabaseName string Owner string - Comment string + Comment *string SecretType string - OauthScopes sql.NullString + OauthScopes []string OwnerRoleType string } @@ -149,6 +149,10 @@ func (s *Secret) ID() SchemaObjectIdentifier { return NewSchemaObjectIdentifier(s.DatabaseName, s.SchemaName, s.Name) } +func (s *Secret) ObjectType() ObjectType { + return ObjectTypeSecret +} + // DescribeSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/desc-secret. type DescribeSecretOptions struct { describe bool `ddl:"static" sql:"DESCRIBE"` @@ -180,6 +184,6 @@ type SecretDetails struct { Username *string OauthAccessTokenExpiryTime *time.Time OauthRefreshTokenExpiryTime *time.Time - OauthScopes *string + OauthScopes []string IntegrationName *string } diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 27f0c50036..01b5ced01a 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -33,8 +33,8 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { opts := defaultOpts() opts.IfNotExists = Bool(true) - opts.SecurityIntegration = integration - opts.OauthScopes = []SecurityIntegrationScope{{"test"}} + opts.ApiIntegration = integration + opts.OauthScopes = []ApiIntegrationScope{{"test"}} opts.Comment = String("foo") assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('test') COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) @@ -73,7 +73,7 @@ func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { opts.IfNotExists = Bool(true) opts.OauthRefreshToken = "foo" opts.OauthRefreshTokenExpiryTime = "bar" - opts.SecurityIntegration = integration + opts.ApiIntegration = integration opts.Comment = String("test") assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 OAUTH_REFRESH_TOKEN = 'foo' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = 'bar' API_AUTHENTICATION = %s COMMENT = 'test'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) @@ -184,17 +184,19 @@ func TestSecrets_Alter(t *testing.T) { assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) }) - t.Run("validation: exactly one field from [opts.Set.SetForOAuthClientCredentialsFlow opts.Set.SetForOAuthAuthorizationFlow opts.Set.SetForBasicAuthentication opts.Set.SetForGenericString] should be present", func(t *testing.T) { + t.Run("validation: conflicting fields for [opts.Set.SetForOAuthClientCredentialsFlow opts.Set.SetForOAuthAuthorizationFlow opts.Set.SetForBasicAuthentication opts.Set.SetForGenericString]", func(t *testing.T) { opts := setOpts() - opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{} - opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{} - assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{{Scope: "foo"}}} + opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{OauthRefreshToken: String("foo"), OauthRefreshTokenExpiryTime: String("bar")} + opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{Username: String("foo"), Password: String("bar")} + opts.Set.SetForGenericString = &SetForGenericString{SecretString: String("secret")} + assertOptsInvalidJoinedErrors(t, opts, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) }) t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { opts := setOpts() opts.Set.Comment = String("test") - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{[]SecurityIntegrationScope{{"sample_scope"}}} + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{[]ApiIntegrationScope{{"sample_scope"}}} assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName()) }) @@ -294,8 +296,10 @@ func TestSecrets_Show(t *testing.T) { t.Run("show with in", func(t *testing.T) { opts := defaultOpts() - opts.In = &In{ - Account: Bool(true), + opts.In = &ExtendedIn{ + In: In{ + Account: Bool(true), + }, } assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS IN ACCOUNT") }) diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index 3321b27380..0786ecb8a7 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -2,6 +2,7 @@ package sdk import ( "context" + "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/collections" ) @@ -53,7 +54,7 @@ func (v *secrets) Show(ctx context.Context, request *ShowSecretRequest) ([]Secre } func (v *secrets) ShowByID(ctx context.Context, id SchemaObjectIdentifier) (*Secret, error) { - request := NewShowSecretRequest().WithIn(In{Schema: id.SchemaId()}).WithLike(Like{String(id.Name())}) + request := NewShowSecretRequest().WithIn(ExtendedIn{In: In{Schema: id.SchemaId()}}).WithLike(Like{String(id.Name())}) secrets, err := v.Show(ctx, request) if err != nil { return nil, err @@ -74,12 +75,12 @@ func (v *secrets) Describe(ctx context.Context, id SchemaObjectIdentifier) (*Sec func (r *CreateWithOAuthClientCredentialsFlowSecretRequest) toOpts() *CreateWithOAuthClientCredentialsFlowSecretOptions { opts := &CreateWithOAuthClientCredentialsFlowSecretOptions{ - OrReplace: r.OrReplace, - IfNotExists: r.IfNotExists, - name: r.name, - SecurityIntegration: r.SecurityIntegration, - OauthScopes: r.OauthScopes, - Comment: r.Comment, + OrReplace: r.OrReplace, + IfNotExists: r.IfNotExists, + name: r.name, + ApiIntegration: r.ApiIntegration, + OauthScopes: r.OauthScopes, + Comment: r.Comment, } return opts } @@ -91,7 +92,7 @@ func (r *CreateWithOAuthAuthorizationCodeFlowSecretRequest) toOpts() *CreateWith name: r.name, OauthRefreshToken: r.OauthRefreshToken, OauthRefreshTokenExpiryTime: r.OauthRefreshTokenExpiryTime, - SecurityIntegration: r.SecurityIntegration, + ApiIntegration: r.ApiIntegration, Comment: r.Comment, } return opts @@ -127,41 +128,53 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { } if r.Set != nil { + opts.Set = &SecretSet{ Comment: r.Set.Comment, } if r.Set.SetForOAuthClientCredentialsFlow != nil { + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{ OauthScopes: r.Set.SetForOAuthClientCredentialsFlow.OauthScopes, } + } if r.Set.SetForOAuthAuthorizationFlow != nil { + opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ OauthRefreshToken: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshToken, OauthRefreshTokenExpiryTime: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshTokenExpiryTime, } + } if r.Set.SetForBasicAuthentication != nil { + opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{ Username: r.Set.SetForBasicAuthentication.Username, Password: r.Set.SetForBasicAuthentication.Password, } + } if r.Set.SetForGenericString != nil { + opts.Set.SetForGenericString = &SetForGenericString{ SecretString: r.Set.SetForGenericString.SecretString, } + } + } if r.Unset != nil { + opts.Unset = &SecretUnset{ Comment: r.Unset.Comment, } + } return opts @@ -183,6 +196,16 @@ func (r *ShowSecretRequest) toOpts() *ShowSecretOptions { return opts } +func getOauthScopes(scopesString string) []string { + formatedScopes := make([]string, 0) + scopesString = strings.TrimPrefix(scopesString, "[") + scopesString = strings.TrimSuffix(scopesString, "]") + for _, scope := range strings.Split(scopesString, ",") { + formatedScopes = append(formatedScopes, strings.TrimSpace(scope)) + } + return formatedScopes +} + func (r secretDBRow) convert() *Secret { s := &Secret{ CreatedOn: r.CreatedOn, @@ -194,10 +217,10 @@ func (r secretDBRow) convert() *Secret { OwnerRoleType: r.OwnerRoleType, } if r.Comment.Valid { - s.Comment = r.Comment.String + s.Comment = String(r.Comment.String) } if r.OauthScopes.Valid { - s.OauthScopes = r.OauthScopes + s.OauthScopes = getOauthScopes(r.OauthScopes.String) } return s } @@ -210,18 +233,27 @@ func (r *DescribeSecretRequest) toOpts() *DescribeSecretOptions { } func (r secretDetailsDBRow) convert() *SecretDetails { - return &SecretDetails{ + s := &SecretDetails{ CreatedOn: r.CreatedOn, Name: r.Name, SchemaName: r.SchemaName, DatabaseName: r.DatabaseName, Owner: r.Owner, - Comment: r.Comment, SecretType: r.SecretType, - Username: r.Username, OauthAccessTokenExpiryTime: r.OauthAccessTokenExpiryTime, OauthRefreshTokenExpiryTime: r.OauthRefreshTokenExpiryTime, - OauthScopes: r.OauthScopes, - IntegrationName: r.IntegrationName, } + if r.Username.Valid { + s.Username = String(r.Username.String) + } + if r.Comment.Valid { + s.Comment = String(r.Comment.String) + } + if r.OauthScopes.Valid { + s.OauthScopes = getOauthScopes(r.OauthScopes.String) + } + if r.IntegrationName.Valid { + s.IntegrationName = String(r.IntegrationName.String) + } + return s } diff --git a/pkg/sdk/secrets_validations_gen.go b/pkg/sdk/secrets_validations_gen.go index c414a5cd6f..b5f7e14800 100644 --- a/pkg/sdk/secrets_validations_gen.go +++ b/pkg/sdk/secrets_validations_gen.go @@ -76,8 +76,8 @@ func (opts *AlterSecretOptions) validate() error { errs = append(errs, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) } if valueSet(opts.Set) { - if !exactlyOneValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { - errs = append(errs, errExactlyOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + if everyValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { + errs = append(errs, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) } } return JoinErrors(errs...) diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index bd50d292e3..a65a7cc61b 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -2,6 +2,8 @@ package testint import ( "database/sql" + assertions "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/objectassert" "testing" "time" @@ -35,13 +37,6 @@ func TestInt_Secrets(t *testing.T) { require.NoError(t, err) t.Cleanup(cleanupIntegration(t, integrationId)) - /* - apiIntegration, dropApiIntegration := testClientHelper().ApiIntegration.CreateApiIntegration(t) - sdk.NewAlterApiIntegrationRequest(apiIntegration.ID()). - WithSet(sdk.NewApiIntegrationSetRequest()) - t.Cleanup(dropApiIntegration) - */ - stringDateToSnowflakeTimeFormat := func(inputLayout, date string) *time.Time { parsedTime, err := time.Parse(inputLayout, date) require.NoError(t, err) @@ -53,17 +48,7 @@ func TestInt_Secrets(t *testing.T) { return &adjustedTime } - /* - cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { - t.Helper() - return func() { - err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) - require.NoError(t, err) - } - } - */ - - createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, scopes []sdk.SecurityIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, scopes []sdk.ApiIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, scopes) @@ -131,97 +116,146 @@ func TestInt_Secrets(t *testing.T) { return secret, id } - assertSecret := func(t *testing.T, s *sdk.Secret, expectedId sdk.SchemaObjectIdentifier, expectedSecretType, expectedComment string) { + createSecretWithId := func(t *testing.T, id sdk.SchemaObjectIdentifier) *sdk.Secret { t.Helper() - assert.Equal(t, expectedId.Name(), s.Name) - assert.Equal(t, expectedSecretType, s.SecretType) - assert.Equal(t, expectedComment, s.Comment) - assert.NotEmpty(t, s.CreatedOn) - assert.NotEmpty(t, s.DatabaseName) - assert.NotEmpty(t, s.SchemaName) - assert.NotEmpty(t, s.OwnerRoleType) - assert.NotEmpty(t, s.Owner) + request := sdk.NewCreateWithGenericStringSecretRequest(id, "foo") + err := client.Secrets.CreateWithGenericString(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret } type secretDetails struct { Name string - Comment string + Comment *string SecretType string - Username string + Username *string OauthAccessTokenExpiryTime *time.Time OauthRefreshTokenExpiryTime *time.Time - OauthScopes string - IntegrationName string + OauthScopes []string + IntegrationName *string } assertSecretDetails := func(actual *sdk.SecretDetails, expected secretDetails) { assert.Equal(t, expected.Name, actual.Name) - assert.Equal(t, expected.Comment, actual.Comment) + assert.EqualValues(t, expected.Comment, actual.Comment) assert.Equal(t, expected.SecretType, actual.SecretType) - assert.Equal(t, expected.Username, actual.Username) + assert.EqualValues(t, expected.Username, actual.Username) assert.Equal(t, expected.OauthAccessTokenExpiryTime, actual.OauthAccessTokenExpiryTime) assert.Equal(t, expected.OauthRefreshTokenExpiryTime, actual.OauthRefreshTokenExpiryTime) - assert.Equal(t, expected.OauthScopes, actual.OauthScopes) - assert.Equal(t, expected.IntegrationName, actual.IntegrationName) + assert.EqualValues(t, expected.OauthScopes, actual.OauthScopes) + assert.EqualValues(t, expected.IntegrationName, actual.IntegrationName) } t.Run("Create: secretWithOAuthClientCredentialsFlow", func(t *testing.T) { - scopes := []sdk.SecurityIntegrationScope{{Scope: "foo"}, {Scope: "bar"}} + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}). + WithComment("a"). + WithIfNotExists(true) + + err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + assertions.AssertThat(t, + objectassert.Secret(t, id). + HasName(id.Name()). + HasComment("a"). + HasSecretType("OAUTH2"). + HasOauthScopes("[foo, bar]"). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()), + ) - secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, scopes, func(req *sdk.CreateWithOAuthClientCredentialsFlowSecretRequest) { - req.WithComment("a"). - WithIfNotExists(true) - }) details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) assertSecretDetails(details, secretDetails{ Name: id.Name(), - Comment: "a", + Comment: sdk.String("a"), SecretType: "OAUTH2", - OauthScopes: "[foo, bar]", - IntegrationName: integrationId.Name(), + OauthScopes: []string{"foo", "bar"}, + IntegrationName: sdk.String(integrationId.Name()), }) - - assertSecret(t, secret, id, "OAUTH2", "a") }) // It is possible to create secret without specifying both refresh token properties and scopes // Scopes are not being inherited from the security_integration what is tested further t.Run("Create: secretWithOAuth - minimal, without token and scopes", func(t *testing.T) { - secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{}, nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, nil) + + err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + assertions.AssertThat(t, + objectassert.Secret(t, id). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()), + ) + details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "OAUTH2", - OauthScopes: "", - OauthAccessTokenExpiryTime: nil, - OauthRefreshTokenExpiryTime: nil, - IntegrationName: integrationId.Name(), + Name: id.Name(), + SecretType: "OAUTH2", + IntegrationName: sdk.String(integrationId.Name()), }) - - assertSecret(t, secret, id, "OAUTH2", "") }) // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret should inherit security_integration scopes, but it does not do so t.Run("Create: SecretWithOAuthClientCredentialsFlow - No Scopes Specified", func(t *testing.T) { - _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{}, nil) - details, err := client.Secrets.Describe(ctx, id) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, []sdk.ApiIntegrationScope{}) + + err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + assertions.AssertThat(t, + objectassert.Secret(t, id). + HasName(id.Name()). + HasOauthScopes("[]"). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()), + ) securityIntegrationProperties, _ := client.SecurityIntegrations.Describe(ctx, integrationId) assert.Contains(t, securityIntegrationProperties, sdk.SecurityIntegrationProperty{Name: "OAUTH_ALLOWED_SCOPES", Type: "List", Value: "[foo, bar]", Default: "[]"}) - assert.NotEqual(t, details.OauthScopes, securityIntegrationProperties) + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + assert.NotEqual(t, details.OauthScopes, "[foo, bar]") }) - t.Run("Create: SecretWithOAuthAuthorizationCodeFlow", func(t *testing.T) { - secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { - req.WithComment("a"). - WithIfNotExists(true) - }) + t.Run("Create: SecretWithOAuthAuthorizationCodeFlow - refreshTokenExpiry date format", func(t *testing.T) { + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithOAuthAuthorizationCodeFlowSecretRequest(id, "foo", refreshTokenExpiryTime, integrationId). + WithComment("a"). + WithIfNotExists(true) + + err := client.Secrets.CreateWithOAuthAuthorizationCodeFlow(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + _, err = client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + assertions.AssertThat(t, + objectassert.Secret(t, id). + HasName(id.Name()). + HasComment("a"). + HasSecretType("OAUTH2"). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()), + ) details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) @@ -229,80 +263,138 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails(details, secretDetails{ Name: id.Name(), SecretType: "OAUTH2", - Comment: "a", + Comment: sdk.String("a"), OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, refreshTokenExpiryTime), - IntegrationName: integrationId.Name(), + IntegrationName: sdk.String(integrationId.Name()), }) + }) - assertSecret(t, secret, id, "OAUTH2", "a") + t.Run("Create: SecretWithOAuthAuthorizationCodeFlow - refreshTokenExpiry datetime format", func(t *testing.T) { + refreshTokenWithTime := refreshTokenExpiryTime + " 12:00:00" + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + request := sdk.NewCreateWithOAuthAuthorizationCodeFlowSecretRequest(id, "foo", refreshTokenWithTime, integrationId) + + err := client.Secrets.CreateWithOAuthAuthorizationCodeFlow(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateTime, refreshTokenWithTime), + IntegrationName: sdk.String(integrationId.Name()), + }) }) t.Run("Create: WithBasicAuthentication", func(t *testing.T) { comment := random.Comment() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, "foo", "foo"). + WithComment(comment). + WithIfNotExists(true) + + err := client.Secrets.CreateWithBasicAuthentication(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + _, err = client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + assertions.AssertThat(t, + objectassert.Secret(t, id). + HasName(id.Name()). + HasComment(comment). + HasSecretType("PASSWORD"). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()), + ) - secret, id := createSecretWithBasicAuthentication(t, "foo", "foo", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { - req.WithComment(comment). - WithIfNotExists(true) - }) details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) assertSecretDetails(details, secretDetails{ Name: id.Name(), - Comment: comment, + Comment: sdk.String(comment), SecretType: "PASSWORD", - Username: "foo", + Username: sdk.String("foo"), }) - - assertSecret(t, secret, id, "PASSWORD", comment) }) t.Run("Create: WithBasicAuthentication - Empty Username and Password", func(t *testing.T) { - comment := random.Comment() - secret, id := createSecretWithBasicAuthentication(t, "", "", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { - req.WithComment(comment). - WithIfNotExists(true) - }) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, "", ""). + WithIfNotExists(true) + + err := client.Secrets.CreateWithBasicAuthentication(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) assertSecretDetails(details, secretDetails{ Name: id.Name(), - Comment: comment, SecretType: "PASSWORD", - Username: "", + Username: sdk.String(""), }) - - assertSecret(t, secret, id, "PASSWORD", comment) }) t.Run("Create: WithGenericString", func(t *testing.T) { comment := random.Comment() - secret, id := createSecretWithGenericString(t, "foo", func(req *sdk.CreateWithGenericStringSecretRequest) { - req.WithComment(comment). - WithIfNotExists(true) - }) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithGenericStringSecretRequest(id, "secret"). + WithComment(comment). + WithIfNotExists(true) - assertSecret(t, secret, id, "GENERIC_STRING", comment) + err := client.Secrets.CreateWithGenericString(ctx, request) + require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) + + _, err = client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + assertions.AssertThat(t, + objectassert.Secret(t, id). + HasName(id.Name()). + HasComment(comment). + HasSecretType("GENERIC_STRING"). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()), + ) }) t.Run("Create: WithGenericString - empty secret_string", func(t *testing.T) { - secret, id := createSecretWithGenericString(t, "", nil) + + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithGenericStringSecretRequest(id, "") + + err := client.Secrets.CreateWithGenericString(ctx, request) require.NoError(t, err) + t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) - assertSecret(t, secret, id, "GENERIC_STRING", "") + assertions.AssertThat(t, + objectassert.Secret(t, id). + HasName(id.Name()). + HasSecretType("GENERIC_STRING"). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()), + ) }) t.Run("Alter: SecretWithOAuthClientCredentials", func(t *testing.T) { comment := random.Comment() - _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) setRequest := sdk.NewAlterSecretRequest(id). WithSet( *sdk.NewSecretSetRequest(). WithComment(comment). WithSetForOAuthClientCredentialsFlow( *sdk.NewSetForOAuthClientCredentialsFlowRequest( - []sdk.SecurityIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}, + []sdk.ApiIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}, ), ), ) @@ -315,9 +407,9 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails(details, secretDetails{ Name: id.Name(), SecretType: "OAUTH2", - Comment: comment, - OauthScopes: "[foo, bar]", - IntegrationName: integrationId.Name(), + Comment: sdk.String(comment), + OauthScopes: sdk.String("[foo, bar]"), + IntegrationName: sdk.String(integrationId.Name()), }) unsetRequest := sdk.NewAlterSecretRequest(id). @@ -358,9 +450,9 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails(details, secretDetails{ Name: id.Name(), SecretType: "OAUTH2", - Comment: comment, + Comment: sdk.String(comment), OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, alteredRefreshTokenExpiryTime), - IntegrationName: integrationId.Name(), + IntegrationName: sdk.String(integrationId.Name()), }) unsetRequest := sdk.NewAlterSecretRequest(id). @@ -401,8 +493,8 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails(details, secretDetails{ Name: id.Name(), SecretType: "PASSWORD", - Comment: comment, - Username: "bar", + Comment: sdk.String(comment), + Username: sdk.String("bar"), }) unsetRequest := sdk.NewAlterSecretRequest(id). @@ -449,7 +541,7 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Drop", func(t *testing.T) { - _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) secret, err := client.Secrets.ShowByID(ctx, id) require.NotNil(t, secret) @@ -471,7 +563,7 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show", func(t *testing.T) { - secretOAuthClientCredentials, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) + secretOAuthClientCredentials, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) @@ -485,11 +577,11 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with Like", func(t *testing.T) { - secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) - secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "bar"}}, nil) + secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) + secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "bar"}}, nil) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ - Pattern: sdk.Pointer(id1.Name()), + Pattern: sdk.String(id1.Name()), })) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret1) @@ -501,7 +593,7 @@ func TestInt_Secrets(t *testing.T) { secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ - Pattern: sdk.Pointer(id1.Name()), + Pattern: sdk.String(id1.Name()), })) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret1) @@ -513,7 +605,7 @@ func TestInt_Secrets(t *testing.T) { secret2, _ := createSecretWithBasicAuthentication(t, "foo_2", "bar_2", nil) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ - Pattern: sdk.Pointer(id1.Name()), + Pattern: sdk.String(id1.Name()), })) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret1) @@ -525,7 +617,7 @@ func TestInt_Secrets(t *testing.T) { secret2, _ := createSecretWithGenericString(t, "foo_2", nil) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ - Pattern: sdk.Pointer(id1.Name()), + Pattern: sdk.String(id1.Name()), })) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret1) @@ -533,17 +625,17 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with In", func(t *testing.T) { - secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) - returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Database: id.DatabaseId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Schema: id.SchemaId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) }) @@ -551,40 +643,40 @@ func TestInt_Secrets(t *testing.T) { t.Run("Show: SecretWithOAuthAuthorizationCodeFlow with In", func(t *testing.T) { secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) - returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Database: id.DatabaseId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Schema: id.SchemaId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) }) t.Run("Show: with In", func(t *testing.T) { - secretOAuthClientCredentials, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{Scope: "foo"}}, nil) + secretOAuthClientCredentials, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) - returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) require.Contains(t, returnedSecrets, *secretBasicAuthentication) require.Contains(t, returnedSecrets, *secretGenericString) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Database: id.DatabaseId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) require.Contains(t, returnedSecrets, *secretBasicAuthentication) require.Contains(t, returnedSecrets, *secretGenericString) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Schema: id.SchemaId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) @@ -595,25 +687,36 @@ func TestInt_Secrets(t *testing.T) { t.Run("Show: SecretWithGenericString with In", func(t *testing.T) { secret, id := createSecretWithGenericString(t, "foo", nil) - returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Database: id.DatabaseId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Schema: id.SchemaId()}})) require.NoError(t, err) require.Contains(t, returnedSecrets, *secret) }) - t.Run("ShowByID", func(t *testing.T) { - _, id := createSecretWithGenericString(t, "foo", nil) + t.Run("ShowByID - same name different schemas", func(t *testing.T) { + schema, schemaCleanup := testClientHelper().Schema.CreateSchema(t) + t.Cleanup(schemaCleanup) - secret, err := client.Secrets.ShowByID(ctx, id) + id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + id2 := testClientHelper().Ids.NewSchemaObjectIdentifierInSchema(id1.Name(), schema.ID()) + + createSecretWithId(t, id1) + createSecretWithId(t, id2) + + secretShowResult1, err := client.Secrets.ShowByID(ctx, id1) + require.NoError(t, err) + require.Equal(t, id1, secretShowResult1.ID()) + + secretShowResult2, err := client.Secrets.ShowByID(ctx, id2) require.NoError(t, err) - assertSecret(t, secret, id, "GENERIC_STRING", "") + require.Equal(t, id2, secretShowResult2.ID()) }) t.Run("Describe", func(t *testing.T) { @@ -626,55 +729,8 @@ func TestInt_Secrets(t *testing.T) { assertSecretDetails(details, secretDetails{ Name: id.Name(), - Comment: "Lorem ipsum", + Comment: sdk.String("Lorem ipsum"), SecretType: "GENERIC_STRING", }) }) } - -func TestInt_SecretsShowWithIn(t *testing.T) { - client := testClient(t) - ctx := testContext(t) - - cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { - t.Helper() - return func() { - err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) - require.NoError(t, err) - } - } - - createSecretWithGenericString := func(t *testing.T, id sdk.SchemaObjectIdentifier, secretString string) *sdk.Secret { - t.Helper() - request := sdk.NewCreateWithGenericStringSecretRequest(id, secretString) - err := client.Secrets.CreateWithGenericString(ctx, request) - require.NoError(t, err) - t.Cleanup(cleanupSecret(t, id)) - - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) - - return secret - } - - t.Run("Show with In - same id in different schemas", func(t *testing.T) { - schema, schemaCleanup := testClientHelper().Schema.CreateSchema(t) - t.Cleanup(schemaCleanup) - - id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() - id2 := testClientHelper().Ids.NewSchemaObjectIdentifierInSchema(id1.Name(), schema.ID()) - - secret1 := createSecretWithGenericString(t, id1, "foo") - secret2 := createSecretWithGenericString(t, id2, "bar") - - returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id1.SchemaId()})) - require.NoError(t, err) - require.Contains(t, returnedSecrets, *secret1) - require.NotContains(t, returnedSecrets, *secret2) - - returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id1.DatabaseId()})) - require.NoError(t, err) - require.Contains(t, returnedSecrets, *secret1) - require.Contains(t, returnedSecrets, *secret2) - }) -} From 2050b85f100e7f4324418ead58e3703c68ee3afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 23 Sep 2024 14:46:07 +0200 Subject: [PATCH 22/34] tests pass after changing to []string for oauthScopes --- .../objectassert/secret_snowflake_gen.go | 13 +- pkg/sdk/secrets_def.go | 2 +- pkg/sdk/secrets_gen.go | 8 +- pkg/sdk/secrets_gen_integration_test.go | 43 ++++ pkg/sdk/secrets_gen_test.go | 232 ++++++++---------- .../testint/secrets_gen_integration_test.go | 15 +- 6 files changed, 159 insertions(+), 154 deletions(-) create mode 100644 pkg/sdk/secrets_gen_integration_test.go diff --git a/pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go b/pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go index 193e09b18e..44ebf3c3ef 100644 --- a/pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go +++ b/pkg/acceptance/bettertestspoc/assert/objectassert/secret_snowflake_gen.go @@ -4,7 +4,9 @@ package objectassert import ( "fmt" + "slices" "testing" + "time" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" @@ -30,7 +32,7 @@ func SecretFromObject(t *testing.T, secret *sdk.Secret) *SecretAssert { } } -func (s *SecretAssert) HasCreatedOn(expected string) *SecretAssert { +func (s *SecretAssert) HasCreatedOn(expected time.Time) *SecretAssert { s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { t.Helper() if o.CreatedOn != expected { @@ -110,14 +112,11 @@ func (s *SecretAssert) HasSecretType(expected string) *SecretAssert { return s } -func (s *SecretAssert) HasOauthScopes(expected string) *SecretAssert { +func (s *SecretAssert) HasOauthScopes(expected []string) *SecretAssert { s.AddAssertion(func(t *testing.T, o *sdk.Secret) error { t.Helper() - if o.OauthScopes == nil { - return fmt.Errorf("expected oauth scopes to have value; got: nil") - } - if *o.OauthScopes != expected { - return fmt.Errorf("expected oauth scopes: %v; got: %v", expected, *o.OauthScopes) + if !slices.Equal(o.OauthScopes, expected) { + return fmt.Errorf("expected oauth scopes: %v; got: %v", expected, o.OauthScopes) } return nil }) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 23f51352d8..80e8227a7c 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -54,7 +54,7 @@ var secretDetails = g.PlainStruct("SecretDetails"). Field("Username", "*string"). Field("OauthAccessTokenExpiryTime", "*time.Time"). Field("OauthRefreshTokenExpiryTime", "*time.Time"). - Field("OauthScopes", "*string"). + Field("OauthScopes", "[]string"). Field("IntegrationName", "*string") var secretSet = g.NewQueryStruct("SecretSet"). diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index 7e35b008bc..39bc7b87a2 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -25,7 +25,7 @@ type CreateWithOAuthClientCredentialsFlowSecretOptions struct { secret bool `ddl:"static" sql:"SECRET"` IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` name SchemaObjectIdentifier `ddl:"identifier"` - secretType string `ddl:"static" sql:"TYPE = OAUTH2"` + Type string `ddl:"static" sql:"TYPE = OAUTH2"` ApiIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` OauthScopes []ApiIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` @@ -55,7 +55,7 @@ type CreateWithBasicAuthenticationSecretOptions struct { secret bool `ddl:"static" sql:"SECRET"` IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` name SchemaObjectIdentifier `ddl:"identifier"` - Type string `ddl:"static" sql:"TYPE = PASSWORD"` + secretType string `ddl:"static" sql:"TYPE = PASSWORD"` Username string `ddl:"parameter,single_quotes" sql:"USERNAME"` Password string `ddl:"parameter,single_quotes" sql:"PASSWORD"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` @@ -160,7 +160,7 @@ type DescribeSecretOptions struct { name SchemaObjectIdentifier `ddl:"identifier"` } type secretDetailsDBRow struct { - CreatedOn string `db:"created_on"` + CreatedOn time.Time `db:"created_on"` Name string `db:"name"` SchemaName string `db:"schema_name"` DatabaseName string `db:"database_name"` @@ -174,7 +174,7 @@ type secretDetailsDBRow struct { IntegrationName sql.NullString `db:"integration_name"` } type SecretDetails struct { - CreatedOn string + CreatedOn time.Time Name string SchemaName string DatabaseName string diff --git a/pkg/sdk/secrets_gen_integration_test.go b/pkg/sdk/secrets_gen_integration_test.go new file mode 100644 index 0000000000..4474555b36 --- /dev/null +++ b/pkg/sdk/secrets_gen_integration_test.go @@ -0,0 +1,43 @@ +package sdk + +import "testing" + +func TestInt_Secrets(t *testing.T) { + // TODO: prepare common resources + + t.Run("CreateWithOAuthClientCredentialsFlow", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("CreateWithBasicAuthentication", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("CreateWithGenericString", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Alter", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Drop", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Show", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("ShowByID", func(t *testing.T) { + // TODO: fill me + }) + + t.Run("Describe", func(t *testing.T) { + // TODO: fill me + }) +} diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 01b5ced01a..5d5b8ebf30 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -3,10 +3,12 @@ package sdk import "testing" func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { - id := randomSchemaObjectIdentifier() + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithOAuthClientCredentialsFlowSecretOptions defaultOpts := func() *CreateWithOAuthClientCredentialsFlowSecretOptions { return &CreateWithOAuthClientCredentialsFlowSecretOptions{ + name: id, } } @@ -15,36 +17,38 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { var opts *CreateWithOAuthClientCredentialsFlowSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: invalid identifier", func(t *testing.T) { + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { opts := defaultOpts() - opts.name = emptySchemaObjectIdentifier + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.OrReplace = Bool(true) + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthClientCredentialsFlowSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("all options", func(t *testing.T) { - integration := randomAccountObjectIdentifier() + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + t.Run("all options", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.ApiIntegration = integration - opts.OauthScopes = []ApiIntegrationScope{{"test"}} - opts.Comment = String("foo") - assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('test') COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { - id := randomSchemaObjectIdentifier() + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithOAuthAuthorizationCodeFlowSecretOptions defaultOpts := func() *CreateWithOAuthAuthorizationCodeFlowSecretOptions { return &CreateWithOAuthAuthorizationCodeFlowSecretOptions{ + name: id, } } @@ -53,37 +57,38 @@ func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { var opts *CreateWithOAuthAuthorizationCodeFlowSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: invalid identifier", func(t *testing.T) { + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { opts := defaultOpts() - opts.name = emptySchemaObjectIdentifier + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.OrReplace = Bool(true) + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthAuthorizationCodeFlowSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("all options", func(t *testing.T) { - integration := randomAccountObjectIdentifier() + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + t.Run("all options", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.OauthRefreshToken = "foo" - opts.OauthRefreshTokenExpiryTime = "bar" - opts.ApiIntegration = integration - opts.Comment = String("test") - assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 OAUTH_REFRESH_TOKEN = 'foo' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = 'bar' API_AUTHENTICATION = %s COMMENT = 'test'", id.FullyQualifiedName(), integration.FullyQualifiedName()) + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } func TestSecrets_CreateWithBasicAuthentication(t *testing.T) { - id := randomSchemaObjectIdentifier() + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithBasicAuthenticationSecretOptions defaultOpts := func() *CreateWithBasicAuthenticationSecretOptions { return &CreateWithBasicAuthenticationSecretOptions{ + name: id, } } @@ -92,34 +97,38 @@ func TestSecrets_CreateWithBasicAuthentication(t *testing.T) { var opts *CreateWithBasicAuthenticationSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: invalid identifier", func(t *testing.T) { + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { opts := defaultOpts() - opts.name = emptySchemaObjectIdentifier + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.OrReplace = Bool(true) + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithBasicAuthenticationSecretOptions", "OrReplace", "IfNotExists")) }) + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + t.Run("all options", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.Username = "foo" - opts.Password = "bar" - opts.Comment = String("test") - assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = PASSWORD USERNAME = 'foo' PASSWORD = 'bar' COMMENT = 'test'", id.FullyQualifiedName()) + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } func TestSecrets_CreateWithGenericString(t *testing.T) { - id := randomSchemaObjectIdentifier() + id := randomSchemaObjectIdentifier() + // Minimal valid CreateWithGenericStringSecretOptions defaultOpts := func() *CreateWithGenericStringSecretOptions { return &CreateWithGenericStringSecretOptions{ + name: id, } } @@ -128,49 +137,39 @@ func TestSecrets_CreateWithGenericString(t *testing.T) { var opts *CreateWithGenericStringSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: invalid identifier", func(t *testing.T) { + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { opts := defaultOpts() - opts.name = emptySchemaObjectIdentifier + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.OrReplace = Bool(true) + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithGenericStringSecretOptions", "OrReplace", "IfNotExists")) }) + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + t.Run("all options", func(t *testing.T) { opts := defaultOpts() - opts.IfNotExists = Bool(true) - opts.SecretString = "test" - assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = GENERIC_STRING SECRET_STRING = 'test'", id.FullyQualifiedName()) + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } func TestSecrets_Alter(t *testing.T) { - id := randomSchemaObjectIdentifier() + id := randomSchemaObjectIdentifier() + // Minimal valid AlterSecretOptions defaultOpts := func() *AlterSecretOptions { return &AlterSecretOptions{ - name: id, - } - } - setOpts := func() *AlterSecretOptions { - return &AlterSecretOptions{ - name: id, - Set: &SecretSet{}, - IfExists: Bool(true), - } - } - - unsetOpts := func() *AlterSecretOptions { - return &AlterSecretOptions{ - name: id, - Unset: &SecretUnset{}, - IfExists: Bool(true), + name: id, } } @@ -178,73 +177,38 @@ func TestSecrets_Alter(t *testing.T) { var opts *AlterSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: exactly one field from [opts.Set opts.Unset] should be present", func(t *testing.T) { opts := defaultOpts() + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) }) t.Run("validation: conflicting fields for [opts.Set.SetForOAuthClientCredentialsFlow opts.Set.SetForOAuthAuthorizationFlow opts.Set.SetForBasicAuthentication opts.Set.SetForGenericString]", func(t *testing.T) { - opts := setOpts() - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{{Scope: "foo"}}} - opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{OauthRefreshToken: String("foo"), OauthRefreshTokenExpiryTime: String("bar")} - opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{Username: String("foo"), Password: String("bar")} - opts.Set.SetForGenericString = &SetForGenericString{SecretString: String("secret")} + opts := defaultOpts() + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) }) - t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { - opts := setOpts() - opts.Set.Comment = String("test") - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{[]ApiIntegrationScope{{"sample_scope"}}} - assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName()) - }) - - t.Run("alter: set options for Oauth Authorization Flow", func(t *testing.T) { - opts := setOpts() - opts.Set.Comment = String("test") - opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ - String("test_token"), - String("2024-11-11"), - } - assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_REFRESH_TOKEN = 'test_token' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2024-11-11'", id.FullyQualifiedName()) - }) - - t.Run("alter: set options for Basic Authentication", func(t *testing.T) { - opts := setOpts() - opts.Set.Comment = String("test") - opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{ - Username: String("foo"), - Password: String("bar"), - } - assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' USERNAME = 'foo' PASSWORD = 'bar'", id.FullyQualifiedName()) - }) - - t.Run("alter: set comment only", func(t *testing.T) { - opts := setOpts() - opts.Set.Comment = String("test") - assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test'", id.FullyQualifiedName()) - }) - - t.Run("alter: set options for Generic string", func(t *testing.T) { - opts := setOpts() - opts.Set.Comment = String("test") - opts.Set.SetForGenericString = &SetForGenericString{String("test")} - assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' SECRET_STRING = 'test'", id.FullyQualifiedName()) + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) - t.Run("alter: unset options", func(t *testing.T) { - opts := unsetOpts() - opts.Unset.Comment = Bool(true) - assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = NULL", id.FullyQualifiedName()) + t.Run("all options", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } func TestSecrets_Drop(t *testing.T) { - id := randomSchemaObjectIdentifier() + id := randomSchemaObjectIdentifier() + // Minimal valid DropSecretOptions defaultOpts := func() *DropSecretOptions { return &DropSecretOptions{ + name: id, } } @@ -253,25 +217,27 @@ func TestSecrets_Drop(t *testing.T) { var opts *DropSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: invalid identifier", func(t *testing.T) { + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { opts := defaultOpts() - opts.name = emptySchemaObjectIdentifier + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("basic", func(t *testing.T) { opts := defaultOpts() - assertOptsValidAndSQLEquals(t, opts, "DROP SECRET %s", id.FullyQualifiedName()) + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) t.Run("all options", func(t *testing.T) { opts := defaultOpts() - opts.IfExists = Bool(true) - assertOptsValidAndSQLEquals(t, opts, "DROP SECRET IF EXISTS %s", id.FullyQualifiedName()) + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } func TestSecrets_Show(t *testing.T) { + // Minimal valid ShowSecretOptions defaultOpts := func() *ShowSecretOptions { return &ShowSecretOptions{} } @@ -283,33 +249,24 @@ func TestSecrets_Show(t *testing.T) { t.Run("basic", func(t *testing.T) { opts := defaultOpts() - assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS") - }) - - t.Run("show with like", func(t *testing.T) { - opts := defaultOpts() - opts.Like = &Like{ - Pattern: String("pattern"), - } - assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS LIKE 'pattern'") + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) - t.Run("show with in", func(t *testing.T) { + t.Run("all options", func(t *testing.T) { opts := defaultOpts() - opts.In = &ExtendedIn{ - In: In{ - Account: Bool(true), - }, - } - assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS IN ACCOUNT") + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } func TestSecrets_Describe(t *testing.T) { - id := randomSchemaObjectIdentifier() + id := randomSchemaObjectIdentifier() + // Minimal valid DescribeSecretOptions defaultOpts := func() *DescribeSecretOptions { return &DescribeSecretOptions{ + name: id, } } @@ -318,14 +275,21 @@ func TestSecrets_Describe(t *testing.T) { var opts *DescribeSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: invalid identifier", func(t *testing.T) { + t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { opts := defaultOpts() - opts.name = emptySchemaObjectIdentifier + // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) + t.Run("basic", func(t *testing.T) { + opts := defaultOpts() + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + }) + t.Run("all options", func(t *testing.T) { opts := defaultOpts() - assertOptsValidAndSQLEquals(t, opts, "DESCRIBE SECRET %s", id.FullyQualifiedName()) + // TODO: fill me + assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") }) } diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index a65a7cc61b..16ad532e8f 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -1,7 +1,6 @@ package testint import ( - "database/sql" assertions "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/objectassert" "testing" @@ -166,7 +165,7 @@ func TestInt_Secrets(t *testing.T) { HasName(id.Name()). HasComment("a"). HasSecretType("OAUTH2"). - HasOauthScopes("[foo, bar]"). + HasOauthScopes([]string{"foo", "bar"}). HasDatabaseName(id.DatabaseName()). HasSchemaName(id.SchemaName()), ) @@ -222,7 +221,7 @@ func TestInt_Secrets(t *testing.T) { assertions.AssertThat(t, objectassert.Secret(t, id). HasName(id.Name()). - HasOauthScopes("[]"). + HasOauthScopes([]string{}). HasDatabaseName(id.DatabaseName()). HasSchemaName(id.SchemaName()), ) @@ -408,7 +407,7 @@ func TestInt_Secrets(t *testing.T) { Name: id.Name(), SecretType: "OAUTH2", Comment: sdk.String(comment), - OauthScopes: sdk.String("[foo, bar]"), + OauthScopes: []string{"foo", "bar"}, IntegrationName: sdk.String(integrationId.Name()), }) @@ -423,7 +422,7 @@ func TestInt_Secrets(t *testing.T) { details, err = client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) + assert.Empty(t, details.Comment) }) t.Run("Alter: SecretWithOAuthAuthorizationCode", func(t *testing.T) { @@ -466,7 +465,7 @@ func TestInt_Secrets(t *testing.T) { details, err = client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) + assert.Empty(t, details.Comment) }) t.Run("Alter: SecretWithBasicAuthorization", func(t *testing.T) { @@ -508,7 +507,7 @@ func TestInt_Secrets(t *testing.T) { details, err = client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) + assert.Empty(t, details.Comment) }) t.Run("Alter: SecretWithGenericString", func(t *testing.T) { @@ -537,7 +536,7 @@ func TestInt_Secrets(t *testing.T) { details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.Equal(t, details.Comment, sql.NullString{String: "", Valid: false}) + assert.Empty(t, details.Comment) }) t.Run("Drop", func(t *testing.T) { From 59c7b147eaec46903ed37cd422d3d610ffae73be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 23 Sep 2024 14:58:39 +0200 Subject: [PATCH 23/34] readded unit tests --- pkg/sdk/secrets_gen_test.go | 232 +++++++++++++++++++++--------------- 1 file changed, 134 insertions(+), 98 deletions(-) diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 5d5b8ebf30..01b5ced01a 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -3,12 +3,10 @@ package sdk import "testing" func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithOAuthClientCredentialsFlowSecretOptions + defaultOpts := func() *CreateWithOAuthClientCredentialsFlowSecretOptions { return &CreateWithOAuthClientCredentialsFlowSecretOptions{ - name: id, } } @@ -17,38 +15,36 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { var opts *CreateWithOAuthClientCredentialsFlowSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthClientCredentialsFlowSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { + integration := randomAccountObjectIdentifier() + opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.ApiIntegration = integration + opts.OauthScopes = []ApiIntegrationScope{{"test"}} + opts.Comment = String("foo") + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('test') COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) } func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithOAuthAuthorizationCodeFlowSecretOptions + defaultOpts := func() *CreateWithOAuthAuthorizationCodeFlowSecretOptions { return &CreateWithOAuthAuthorizationCodeFlowSecretOptions{ - name: id, } } @@ -57,38 +53,37 @@ func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { var opts *CreateWithOAuthAuthorizationCodeFlowSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithOAuthAuthorizationCodeFlowSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { + integration := randomAccountObjectIdentifier() + opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.OauthRefreshToken = "foo" + opts.OauthRefreshTokenExpiryTime = "bar" + opts.ApiIntegration = integration + opts.Comment = String("test") + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 OAUTH_REFRESH_TOKEN = 'foo' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = 'bar' API_AUTHENTICATION = %s COMMENT = 'test'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) } func TestSecrets_CreateWithBasicAuthentication(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithBasicAuthenticationSecretOptions + defaultOpts := func() *CreateWithBasicAuthenticationSecretOptions { return &CreateWithBasicAuthenticationSecretOptions{ - name: id, } } @@ -97,38 +92,34 @@ func TestSecrets_CreateWithBasicAuthentication(t *testing.T) { var opts *CreateWithBasicAuthenticationSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithBasicAuthenticationSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.Username = "foo" + opts.Password = "bar" + opts.Comment = String("test") + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = PASSWORD USERNAME = 'foo' PASSWORD = 'bar' COMMENT = 'test'", id.FullyQualifiedName()) }) } func TestSecrets_CreateWithGenericString(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid CreateWithGenericStringSecretOptions + defaultOpts := func() *CreateWithGenericStringSecretOptions { return &CreateWithGenericStringSecretOptions{ - name: id, } } @@ -137,78 +128,123 @@ func TestSecrets_CreateWithGenericString(t *testing.T) { var opts *CreateWithGenericStringSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("validation: conflicting fields for [opts.OrReplace opts.IfNotExists]", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.IfNotExists = Bool(true) + opts.OrReplace = Bool(true) assertOptsInvalidJoinedErrors(t, opts, errOneOf("CreateWithGenericStringSecretOptions", "OrReplace", "IfNotExists")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfNotExists = Bool(true) + opts.SecretString = "test" + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = GENERIC_STRING SECRET_STRING = 'test'", id.FullyQualifiedName()) }) } func TestSecrets_Alter(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid AlterSecretOptions + defaultOpts := func() *AlterSecretOptions { return &AlterSecretOptions{ - name: id, } } + setOpts := func() *AlterSecretOptions { + return &AlterSecretOptions{ + name: id, + Set: &SecretSet{}, + IfExists: Bool(true), + } + } + + unsetOpts := func() *AlterSecretOptions { + return &AlterSecretOptions{ + name: id, + Unset: &SecretUnset{}, + IfExists: Bool(true), + } + } + t.Run("validation: nil options", func(t *testing.T) { var opts *AlterSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) + t.Run("validation: exactly one field from [opts.Set opts.Unset] should be present", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me assertOptsInvalidJoinedErrors(t, opts, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) }) t.Run("validation: conflicting fields for [opts.Set.SetForOAuthClientCredentialsFlow opts.Set.SetForOAuthAuthorizationFlow opts.Set.SetForBasicAuthentication opts.Set.SetForGenericString]", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me + opts := setOpts() + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{{Scope: "foo"}}} + opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{OauthRefreshToken: String("foo"), OauthRefreshTokenExpiryTime: String("bar")} + opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{Username: String("foo"), Password: String("bar")} + opts.Set.SetForGenericString = &SetForGenericString{SecretString: String("secret")} assertOptsInvalidJoinedErrors(t, opts, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{[]ApiIntegrationScope{{"sample_scope"}}} + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName()) }) - t.Run("all options", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + t.Run("alter: set options for Oauth Authorization Flow", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ + String("test_token"), + String("2024-11-11"), + } + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_REFRESH_TOKEN = 'test_token' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2024-11-11'", id.FullyQualifiedName()) + }) + + t.Run("alter: set options for Basic Authentication", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{ + Username: String("foo"), + Password: String("bar"), + } + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' USERNAME = 'foo' PASSWORD = 'bar'", id.FullyQualifiedName()) + }) + + t.Run("alter: set comment only", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test'", id.FullyQualifiedName()) + }) + + t.Run("alter: set options for Generic string", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForGenericString = &SetForGenericString{String("test")} + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' SECRET_STRING = 'test'", id.FullyQualifiedName()) + }) + + t.Run("alter: unset options", func(t *testing.T) { + opts := unsetOpts() + opts.Unset.Comment = Bool(true) + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = NULL", id.FullyQualifiedName()) }) } func TestSecrets_Drop(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid DropSecretOptions + defaultOpts := func() *DropSecretOptions { return &DropSecretOptions{ - name: id, } } @@ -217,27 +253,25 @@ func TestSecrets_Drop(t *testing.T) { var opts *DropSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) t.Run("basic", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + assertOptsValidAndSQLEquals(t, opts, "DROP SECRET %s", id.FullyQualifiedName()) }) t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.IfExists = Bool(true) + assertOptsValidAndSQLEquals(t, opts, "DROP SECRET IF EXISTS %s", id.FullyQualifiedName()) }) } func TestSecrets_Show(t *testing.T) { - // Minimal valid ShowSecretOptions defaultOpts := func() *ShowSecretOptions { return &ShowSecretOptions{} } @@ -249,24 +283,33 @@ func TestSecrets_Show(t *testing.T) { t.Run("basic", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS") }) - t.Run("all options", func(t *testing.T) { + t.Run("show with like", func(t *testing.T) { + opts := defaultOpts() + opts.Like = &Like{ + Pattern: String("pattern"), + } + assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS LIKE 'pattern'") + }) + + t.Run("show with in", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + opts.In = &ExtendedIn{ + In: In{ + Account: Bool(true), + }, + } + assertOptsValidAndSQLEquals(t, opts, "SHOW SECRETS IN ACCOUNT") }) } func TestSecrets_Describe(t *testing.T) { - id := randomSchemaObjectIdentifier() - // Minimal valid DescribeSecretOptions + defaultOpts := func() *DescribeSecretOptions { return &DescribeSecretOptions{ - name: id, } } @@ -275,21 +318,14 @@ func TestSecrets_Describe(t *testing.T) { var opts *DescribeSecretOptions = nil assertOptsInvalidJoinedErrors(t, opts, ErrNilOptions) }) - t.Run("validation: valid identifier for [opts.name]", func(t *testing.T) { + t.Run("validation: invalid identifier", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me + opts.name = emptySchemaObjectIdentifier assertOptsInvalidJoinedErrors(t, opts, ErrInvalidObjectIdentifier) }) - t.Run("basic", func(t *testing.T) { - opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") - }) - t.Run("all options", func(t *testing.T) { opts := defaultOpts() - // TODO: fill me - assertOptsValidAndSQLEquals(t, opts, "TODO: fill me") + assertOptsValidAndSQLEquals(t, opts, "DESCRIBE SECRET %s", id.FullyQualifiedName()) }) } From df7a8ff42eab42c7f56edf575a8fc100e9ce7d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 24 Sep 2024 09:46:53 +0200 Subject: [PATCH 24/34] added CreateApiAuthenticationWithRequest to security integration client --- .../helpers/security_integration_client.go | 13 +++++++++++++ pkg/sdk/security_integrations_dto_gen.go | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/pkg/acceptance/helpers/security_integration_client.go b/pkg/acceptance/helpers/security_integration_client.go index 23b84c500f..5931b8fa9d 100644 --- a/pkg/acceptance/helpers/security_integration_client.go +++ b/pkg/acceptance/helpers/security_integration_client.go @@ -56,6 +56,19 @@ func (c *SecurityIntegrationClient) CreateScim(t *testing.T) (*sdk.SecurityInteg return c.CreateScimWithRequest(t, sdk.NewCreateScimSecurityIntegrationRequest(c.ids.RandomAccountObjectIdentifier(), sdk.ScimSecurityIntegrationScimClientGeneric, sdk.ScimSecurityIntegrationRunAsRoleGenericScimProvisioner)) } +func (c *SecurityIntegrationClient) CreateApiAuthenticationClientCredentialsWithRequest(t *testing.T, request *sdk.CreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest) (*sdk.SecurityIntegration, func()) { + t.Helper() + ctx := context.Background() + + err := c.client().CreateApiAuthenticationWithClientCredentialsFlow(ctx, request) + require.NoError(t, err) + + si, err := c.client().ShowByID(ctx, request.GetName()) + require.NoError(t, err) + + return si, c.DropSecurityIntegrationFunc(t, request.GetName()) +} + func (c *SecurityIntegrationClient) UpdateSaml2(t *testing.T, request *sdk.AlterSaml2SecurityIntegrationRequest) { t.Helper() ctx := context.Background() diff --git a/pkg/sdk/security_integrations_dto_gen.go b/pkg/sdk/security_integrations_dto_gen.go index 7726e8d8b8..43b2d73aae 100644 --- a/pkg/sdk/security_integrations_dto_gen.go +++ b/pkg/sdk/security_integrations_dto_gen.go @@ -40,6 +40,10 @@ type CreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest Comment *string } +func (r *CreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest) GetName() AccountObjectIdentifier { + return r.name +} + type CreateApiAuthenticationWithAuthorizationCodeGrantFlowSecurityIntegrationRequest struct { OrReplace *bool IfNotExists *bool From eed310a33f6504e4c6efdfb888b33adf06baa05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 24 Sep 2024 09:47:23 +0200 Subject: [PATCH 25/34] changes to secret after review, all tests pass --- pkg/acceptance/helpers/secret_client.go | 44 +++- pkg/sdk/secrets_def.go | 6 +- pkg/sdk/secrets_gen.go | 6 +- pkg/sdk/secrets_gen_test.go | 27 +- .../testint/secrets_gen_integration_test.go | 236 ++++++++---------- 5 files changed, 181 insertions(+), 138 deletions(-) diff --git a/pkg/acceptance/helpers/secret_client.go b/pkg/acceptance/helpers/secret_client.go index 314f6248b5..f2657b39bb 100644 --- a/pkg/acceptance/helpers/secret_client.go +++ b/pkg/acceptance/helpers/secret_client.go @@ -25,7 +25,35 @@ func (c *SecretClient) client() sdk.Secrets { return c.context.client.Secrets } -func (c *SecretClient) CreateWithBasicFlow(t *testing.T, id sdk.SchemaObjectIdentifier, username, password string) (*sdk.Secret, func()) { +func (c *SecretClient) CreateWithOAuthClientCredentialsFlow(t *testing.T, id sdk.SchemaObjectIdentifier, apiIntegration sdk.AccountObjectIdentifier, oauthScopes []sdk.ApiIntegrationScope) (*sdk.Secret, func()) { + t.Helper() + ctx := context.Background() + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, apiIntegration, oauthScopes) + + err := c.client().CreateWithOAuthClientCredentialsFlow(ctx, request) + require.NoError(t, err) + + secret, err := c.client().ShowByID(ctx, id) + require.NoError(t, err) + + return secret, c.DropFunc(t, id) +} + +func (c *SecretClient) CreateWithOAuthAuthorizationCodeFlow(t *testing.T, id sdk.SchemaObjectIdentifier, apiIntegration sdk.AccountObjectIdentifier, refreshToken, refreshTokenExpiryTime string) (*sdk.Secret, func()) { + t.Helper() + ctx := context.Background() + request := sdk.NewCreateWithOAuthAuthorizationCodeFlowSecretRequest(id, refreshToken, refreshTokenExpiryTime, apiIntegration) + + err := c.client().CreateWithOAuthAuthorizationCodeFlow(ctx, request) + require.NoError(t, err) + + secret, err := c.client().ShowByID(ctx, id) + require.NoError(t, err) + + return secret, c.DropFunc(t, id) +} + +func (c *SecretClient) CreateWithBasicAuthenticationFlow(t *testing.T, id sdk.SchemaObjectIdentifier, username, password string) (*sdk.Secret, func()) { t.Helper() ctx := context.Background() request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password) @@ -39,6 +67,20 @@ func (c *SecretClient) CreateWithBasicFlow(t *testing.T, id sdk.SchemaObjectIden return secret, c.DropFunc(t, id) } +func (c *SecretClient) CreateWithGenericString(t *testing.T, id sdk.SchemaObjectIdentifier, secretString string) (*sdk.Secret, func()) { + t.Helper() + ctx := context.Background() + request := sdk.NewCreateWithGenericStringSecretRequest(id, secretString) + + err := c.client().CreateWithGenericString(ctx, request) + require.NoError(t, err) + + secret, err := c.client().ShowByID(ctx, id) + require.NoError(t, err) + + return secret, c.DropFunc(t, id) +} + func (c *SecretClient) DropFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { t.Helper() ctx := context.Background() diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 80e8227a7c..d4edb0494f 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -104,7 +104,7 @@ var SecretsDef = g.NewInterface( SQL("SECRET"). IfNotExists(). Name(). - PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). + PredefinedQueryStructField("secretType", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). Identifier("ApiIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). ListAssignment("OAUTH_SCOPES", "ApiIntegrationScope", g.ParameterOptions().Parentheses().Required()). OptionalComment(). @@ -120,7 +120,7 @@ var SecretsDef = g.NewInterface( SQL("SECRET"). IfNotExists(). Name(). - PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). + PredefinedQueryStructField("secretType", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). TextAssignment("OAUTH_REFRESH_TOKEN", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). TextAssignment("OAUTH_REFRESH_TOKEN_EXPIRY_TIME", g.ParameterOptions().NoParentheses().SingleQuotes().Required()). Identifier("ApiIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). @@ -152,7 +152,7 @@ var SecretsDef = g.NewInterface( SQL("SECRET"). IfNotExists(). Name(). - PredefinedQueryStructField("Type", "string", g.StaticOptions().SQL("TYPE = GENERIC_STRING")). + PredefinedQueryStructField("secretType", "string", g.StaticOptions().SQL("TYPE = GENERIC_STRING")). TextAssignment("SECRET_STRING", g.ParameterOptions().SingleQuotes().Required()). OptionalComment(). WithValidation(g.ValidIdentifier, "name"). diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index 39bc7b87a2..8a5a819e5f 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -25,7 +25,7 @@ type CreateWithOAuthClientCredentialsFlowSecretOptions struct { secret bool `ddl:"static" sql:"SECRET"` IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` name SchemaObjectIdentifier `ddl:"identifier"` - Type string `ddl:"static" sql:"TYPE = OAUTH2"` + secretType string `ddl:"static" sql:"TYPE = OAUTH2"` ApiIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` OauthScopes []ApiIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` @@ -41,7 +41,7 @@ type CreateWithOAuthAuthorizationCodeFlowSecretOptions struct { secret bool `ddl:"static" sql:"SECRET"` IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` name SchemaObjectIdentifier `ddl:"identifier"` - Type string `ddl:"static" sql:"TYPE = OAUTH2"` + secretType string `ddl:"static" sql:"TYPE = OAUTH2"` OauthRefreshToken string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` OauthRefreshTokenExpiryTime string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN_EXPIRY_TIME"` ApiIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` @@ -68,7 +68,7 @@ type CreateWithGenericStringSecretOptions struct { secret bool `ddl:"static" sql:"SECRET"` IfNotExists *bool `ddl:"keyword" sql:"IF NOT EXISTS"` name SchemaObjectIdentifier `ddl:"identifier"` - Type string `ddl:"static" sql:"TYPE = GENERIC_STRING"` + secretType string `ddl:"static" sql:"TYPE = GENERIC_STRING"` SecretString string `ddl:"parameter,single_quotes" sql:"SECRET_STRING"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` } diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 01b5ced01a..35a4a86988 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -38,6 +38,17 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { opts.Comment = String("foo") assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('test') COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) + + t.Run("empty oauth scopes list", func(t *testing.T) { + integration := randomAccountObjectIdentifier() + + opts := defaultOpts() + opts.IfNotExists = Bool(true) + opts.ApiIntegration = integration + opts.OauthScopes = []ApiIntegrationScope{} + opts.Comment = String("foo") + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) + }) } func TestSecrets_CreateWithOAuthAuthorizationCodeFlow(t *testing.T) { @@ -143,9 +154,10 @@ func TestSecrets_CreateWithGenericString(t *testing.T) { t.Run("all options", func(t *testing.T) { opts := defaultOpts() + opts.Comment = String("test") opts.IfNotExists = Bool(true) opts.SecretString = "test" - assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = GENERIC_STRING SECRET_STRING = 'test'", id.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = GENERIC_STRING SECRET_STRING = 'test' COMMENT = 'test'", id.FullyQualifiedName()) }) } @@ -196,16 +208,23 @@ func TestSecrets_Alter(t *testing.T) { t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { opts := setOpts() opts.Set.Comment = String("test") - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{[]ApiIntegrationScope{{"sample_scope"}}} + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{{"sample_scope"}}} assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName()) }) + t.Run("alter: set options for Oauth Client Credentials Flow - empty oauth scopes list", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{}} + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test'", id.FullyQualifiedName()) + }) + t.Run("alter: set options for Oauth Authorization Flow", func(t *testing.T) { opts := setOpts() opts.Set.Comment = String("test") opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ - String("test_token"), - String("2024-11-11"), + OauthRefreshToken: String("test_token"), + OauthRefreshTokenExpiryTime: String("2024-11-11"), } assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_REFRESH_TOKEN = 'test_token' OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2024-11-11'", id.FullyQualifiedName()) }) diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 16ad532e8f..e09ef680e3 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -17,24 +17,13 @@ func TestInt_Secrets(t *testing.T) { ctx := testContext(t) integrationId := testClientHelper().Ids.RandomAccountObjectIdentifier() - refreshTokenExpiryTime := time.Now().Add(24 * time.Hour).Format(time.DateOnly) - cleanupIntegration := func(t *testing.T, integrationId sdk.AccountObjectIdentifier) func() { - t.Helper() - return func() { - err := client.SecurityIntegrations.Drop(ctx, sdk.NewDropSecurityIntegrationRequest(integrationId).WithIfExists(true)) - require.NoError(t, err) - } - } - - err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow( - ctx, + _, apiIntegrationCleanup := testClientHelper().SecurityIntegration.CreateApiAuthenticationClientCredentialsWithRequest(t, sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). WithOauthAllowedScopes([]sdk.AllowedScope{{Scope: "foo"}, {Scope: "bar"}}), ) - require.NoError(t, err) - t.Cleanup(cleanupIntegration(t, integrationId)) + t.Cleanup(apiIntegrationCleanup) stringDateToSnowflakeTimeFormat := func(inputLayout, date string) *time.Time { parsedTime, err := time.Parse(inputLayout, date) @@ -47,87 +36,6 @@ func TestInt_Secrets(t *testing.T) { return &adjustedTime } - createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, scopes []sdk.ApiIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { - t.Helper() - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, scopes) - if with != nil { - with(request) - } - err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) - require.NoError(t, err) - t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) - - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) - - return secret, id - } - - createSecretWithOAuthAuthorizationCodeFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, refreshToken, refreshTokenExpiryTime string, with func(*sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { - t.Helper() - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithOAuthAuthorizationCodeFlowSecretRequest(id, refreshToken, refreshTokenExpiryTime, integrationId) - if with != nil { - with(request) - } - err := client.Secrets.CreateWithOAuthAuthorizationCodeFlow(ctx, request) - require.NoError(t, err) - t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) - - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) - - return secret, id - } - - createSecretWithBasicAuthentication := func(t *testing.T, username, password string, with func(*sdk.CreateWithBasicAuthenticationSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { - t.Helper() - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password) - if with != nil { - with(request) - } - err := client.Secrets.CreateWithBasicAuthentication(ctx, request) - require.NoError(t, err) - t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) - - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) - - return secret, id - } - - createSecretWithGenericString := func(t *testing.T, secretString string, with func(options *sdk.CreateWithGenericStringSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { - t.Helper() - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithGenericStringSecretRequest(id, secretString) - if with != nil { - with(request) - } - err := client.Secrets.CreateWithGenericString(ctx, request) - require.NoError(t, err) - t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) - - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) - - return secret, id - } - - createSecretWithId := func(t *testing.T, id sdk.SchemaObjectIdentifier) *sdk.Secret { - t.Helper() - request := sdk.NewCreateWithGenericStringSecretRequest(id, "foo") - err := client.Secrets.CreateWithGenericString(ctx, request) - require.NoError(t, err) - t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) - - secret, err := client.Secrets.ShowByID(ctx, id) - require.NoError(t, err) - - return secret - } - type secretDetails struct { Name string Comment *string @@ -209,8 +117,8 @@ func TestInt_Secrets(t *testing.T) { }) }) - // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret should inherit security_integration scopes, but it does not do so - t.Run("Create: SecretWithOAuthClientCredentialsFlow - No Scopes Specified", func(t *testing.T) { + // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret with empty oauth_scopes list should inherit scopes from security_integration, but it does not + t.Run("Create: SecretWithOAuthClientCredentialsFlow - Empty Scopes List", func(t *testing.T) { id := testClientHelper().Ids.RandomSchemaObjectIdentifier() request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, []sdk.ApiIntegrationScope{}) @@ -231,7 +139,10 @@ func TestInt_Secrets(t *testing.T) { details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) - assert.NotEqual(t, details.OauthScopes, "[foo, bar]") + + assert.NotContains(t, details.OauthScopes, "foo") + assert.NotContains(t, details.OauthScopes, "bar") + assert.Empty(t, details.OauthScopes) }) t.Run("Create: SecretWithOAuthAuthorizationCodeFlow - refreshTokenExpiry date format", func(t *testing.T) { @@ -386,7 +297,10 @@ func TestInt_Secrets(t *testing.T) { t.Run("Alter: SecretWithOAuthClientCredentials", func(t *testing.T) { comment := random.Comment() - _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + _, secretDropFunc := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, id, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}) + t.Cleanup(secretDropFunc) + setRequest := sdk.NewAlterSecretRequest(id). WithSet( *sdk.NewSecretSetRequest(). @@ -429,7 +343,11 @@ func TestInt_Secrets(t *testing.T) { comment := random.Comment() alteredRefreshTokenExpiryTime := time.Now().Add(4 * 24 * time.Hour).Format(time.DateOnly) - _, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + _, secretCleanup := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id, integrationId, "foo", refreshTokenExpiryTime) + t.Cleanup(secretCleanup) + + //_, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) setRequest := sdk.NewAlterSecretRequest(id). WithSet( *sdk.NewSecretSetRequest(). @@ -470,8 +388,11 @@ func TestInt_Secrets(t *testing.T) { t.Run("Alter: SecretWithBasicAuthorization", func(t *testing.T) { comment := random.Comment() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + _, secretCleanup := testClientHelper().Secret.CreateWithBasicAuthenticationFlow(t, id, "foo", "foo") + t.Cleanup(secretCleanup) - _, id := createSecretWithBasicAuthentication(t, "foo", "foo", nil) setRequest := sdk.NewAlterSecretRequest(id). WithSet( *sdk.NewSecretSetRequest(). @@ -512,7 +433,10 @@ func TestInt_Secrets(t *testing.T) { t.Run("Alter: SecretWithGenericString", func(t *testing.T) { comment := random.Comment() - _, id := createSecretWithGenericString(t, "foo", nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + _, secretCleanup := testClientHelper().Secret.CreateWithGenericString(t, id, "foo") + t.Cleanup(secretCleanup) setRequest := sdk.NewAlterSecretRequest(id). WithSet( *sdk.NewSecretSetRequest(). @@ -540,7 +464,10 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Drop", func(t *testing.T) { - _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) + //_, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + _, secretCleanup := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, id, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}) + t.Cleanup(secretCleanup) secret, err := client.Secrets.ShowByID(ctx, id) require.NotNil(t, secret) @@ -562,10 +489,17 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show", func(t *testing.T) { - secretOAuthClientCredentials, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) - secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) - secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) - secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) + secretOAuthClientCredentials, secretCleanupClientCredentialsFlow := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}) + t.Cleanup(secretCleanupClientCredentialsFlow) + + secretOAuthAuthorizationCode, secretCleanupAuthorizationCodeFlow := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), integrationId, "foo", refreshTokenExpiryTime) + t.Cleanup(secretCleanupAuthorizationCodeFlow) + + secretBasicAuthentication, secretCleanupBasicAuthentication := testClientHelper().Secret.CreateWithBasicAuthenticationFlow(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), "foo", "bar") + t.Cleanup(secretCleanupBasicAuthentication) + + secretGenericString, secretCleanupGenericString := testClientHelper().Secret.CreateWithGenericString(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), "foo") + t.Cleanup(secretCleanupGenericString) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest()) require.NoError(t, err) @@ -576,8 +510,16 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with Like", func(t *testing.T) { - secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) - secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "bar"}}, nil) + //secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) + //secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "bar"}}, nil) + id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + secret1, secretCleanup1 := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, id1, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}) + t.Cleanup(secretCleanup1) + + secret2, secretCleanup2 := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, id2, integrationId, []sdk.ApiIntegrationScope{{Scope: "bar"}}) + t.Cleanup(secretCleanup2) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ Pattern: sdk.String(id1.Name()), @@ -588,8 +530,17 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthAuthorization with Like", func(t *testing.T) { - secret1, id1 := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_1", refreshTokenExpiryTime, nil) - secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) + //secret2, id1 := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_1", refreshTokenExpiryTime, nil) + //secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) + + id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + secret1, secretCleanup1 := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id1, integrationId, "foo", refreshTokenExpiryTime) + t.Cleanup(secretCleanup1) + + secret2, secretCleanup2 := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id2, integrationId, "bar", refreshTokenExpiryTime) + t.Cleanup(secretCleanup2) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ Pattern: sdk.String(id1.Name()), @@ -600,8 +551,14 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithBasicAuthentication with Like", func(t *testing.T) { - secret1, id1 := createSecretWithBasicAuthentication(t, "foo_1", "bar_1", nil) - secret2, _ := createSecretWithBasicAuthentication(t, "foo_2", "bar_2", nil) + id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + secret1, secretCleanup1 := testClientHelper().Secret.CreateWithBasicAuthenticationFlow(t, id1, "foo", "foo") + t.Cleanup(secretCleanup1) + + secret2, secretCleanup2 := testClientHelper().Secret.CreateWithBasicAuthenticationFlow(t, id2, "bar", "bar") + t.Cleanup(secretCleanup2) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ Pattern: sdk.String(id1.Name()), @@ -612,8 +569,14 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithGenericString with Like", func(t *testing.T) { - secret1, id1 := createSecretWithGenericString(t, "foo_1", nil) - secret2, _ := createSecretWithGenericString(t, "foo_2", nil) + id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + secret1, secretCleanup1 := testClientHelper().Secret.CreateWithGenericString(t, id1, "foo") + t.Cleanup(secretCleanup1) + + secret2, secretCleanup2 := testClientHelper().Secret.CreateWithGenericString(t, id2, "bar") + t.Cleanup(secretCleanup2) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ Pattern: sdk.String(id1.Name()), @@ -624,7 +587,9 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with In", func(t *testing.T) { - secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + secret, secretCleanup := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, id, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}) + t.Cleanup(secretCleanup) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) @@ -640,7 +605,11 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthAuthorizationCodeFlow with In", func(t *testing.T) { - secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + //secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + secret, secretCleanup := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id, integrationId, "foo", refreshTokenExpiryTime) + t.Cleanup(secretCleanup) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) @@ -656,10 +625,19 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: with In", func(t *testing.T) { - secretOAuthClientCredentials, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) - secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) - secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) - secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + secretOAuthClientCredentials, secretCleanupClientCredentialsFlow := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}) + t.Cleanup(secretCleanupClientCredentialsFlow) + + secretOAuthAuthorizationCode, secretCleanupAuthorizationFlow := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), integrationId, "foo", refreshTokenExpiryTime) + t.Cleanup(secretCleanupAuthorizationFlow) + + secretBasicAuthentication, secretCleanupBasicAuthentication := testClientHelper().Secret.CreateWithBasicAuthenticationFlow(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), "foo", "foo") + t.Cleanup(secretCleanupBasicAuthentication) + + secretGenericString, secretCleanupWithGenericString := testClientHelper().Secret.CreateWithGenericString(t, testClientHelper().Ids.RandomSchemaObjectIdentifier(), "foo") + t.Cleanup(secretCleanupWithGenericString) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) @@ -684,7 +662,9 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithGenericString with In", func(t *testing.T) { - secret, id := createSecretWithGenericString(t, "foo", nil) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + secret, secretCleanup := testClientHelper().Secret.CreateWithGenericString(t, id, "foo") + t.Cleanup(secretCleanup) returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.ExtendedIn{In: sdk.In{Account: sdk.Pointer(true)}})) require.NoError(t, err) @@ -706,8 +686,11 @@ func TestInt_Secrets(t *testing.T) { id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() id2 := testClientHelper().Ids.NewSchemaObjectIdentifierInSchema(id1.Name(), schema.ID()) - createSecretWithId(t, id1) - createSecretWithId(t, id2) + _, cleanup1 := testClientHelper().Secret.CreateWithGenericString(t, id1, "foo") + t.Cleanup(cleanup1) + + _, cleanup2 := testClientHelper().Secret.CreateWithGenericString(t, id2, "bar") + t.Cleanup(cleanup2) secretShowResult1, err := client.Secrets.ShowByID(ctx, id1) require.NoError(t, err) @@ -719,16 +702,15 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Describe", func(t *testing.T) { - _, id := createSecretWithGenericString(t, "foo", func(req *sdk.CreateWithGenericStringSecretRequest) { - req.WithComment("Lorem ipsum") - }) + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + _, secretCleanup := testClientHelper().Secret.CreateWithGenericString(t, id, "foo") + t.Cleanup(secretCleanup) details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) assertSecretDetails(details, secretDetails{ Name: id.Name(), - Comment: sdk.String("Lorem ipsum"), SecretType: "GENERIC_STRING", }) }) From af2e0306905dc35892959154416d90cc23d0a568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 24 Sep 2024 09:56:24 +0200 Subject: [PATCH 26/34] added assert for details --- pkg/sdk/testint/secrets_gen_integration_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index e09ef680e3..ba04602865 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -454,12 +454,19 @@ func TestInt_Secrets(t *testing.T) { *sdk.NewSecretUnsetRequest(). WithComment(true), ) + err = client.Secrets.Alter(ctx, unsetRequest) require.NoError(t, err) details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "GENERIC_STRING", + Comment: nil, + }) + assert.Empty(t, details.Comment) }) From 4ccc4e7c6e391151251af148c4f0d03d559d2344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 24 Sep 2024 09:58:54 +0200 Subject: [PATCH 27/34] linter hints applied --- pkg/sdk/secrets_impl_gen.go | 12 ------------ .../testint/secrets_gen_integration_test.go | 18 ++++++++---------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index 0786ecb8a7..4464553f9a 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -128,53 +128,41 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { } if r.Set != nil { - opts.Set = &SecretSet{ Comment: r.Set.Comment, } if r.Set.SetForOAuthClientCredentialsFlow != nil { - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{ OauthScopes: r.Set.SetForOAuthClientCredentialsFlow.OauthScopes, } - } if r.Set.SetForOAuthAuthorizationFlow != nil { - opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{ OauthRefreshToken: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshToken, OauthRefreshTokenExpiryTime: r.Set.SetForOAuthAuthorizationFlow.OauthRefreshTokenExpiryTime, } - } if r.Set.SetForBasicAuthentication != nil { - opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{ Username: r.Set.SetForBasicAuthentication.Username, Password: r.Set.SetForBasicAuthentication.Password, } - } if r.Set.SetForGenericString != nil { - opts.Set.SetForGenericString = &SetForGenericString{ SecretString: r.Set.SetForGenericString.SecretString, } - } - } if r.Unset != nil { - opts.Unset = &SecretUnset{ Comment: r.Unset.Comment, } - } return opts diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index ba04602865..76df4308ef 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -1,11 +1,12 @@ package testint import ( - assertions "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/objectassert" "testing" "time" + assertions "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/objectassert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/stretchr/testify/assert" @@ -278,7 +279,6 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Create: WithGenericString - empty secret_string", func(t *testing.T) { - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() request := sdk.NewCreateWithGenericStringSecretRequest(id, "") @@ -347,7 +347,6 @@ func TestInt_Secrets(t *testing.T) { _, secretCleanup := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id, integrationId, "foo", refreshTokenExpiryTime) t.Cleanup(secretCleanup) - //_, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) setRequest := sdk.NewAlterSecretRequest(id). WithSet( *sdk.NewSecretSetRequest(). @@ -471,7 +470,6 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Drop", func(t *testing.T) { - //_, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) id := testClientHelper().Ids.RandomSchemaObjectIdentifier() _, secretCleanup := testClientHelper().Secret.CreateWithOAuthClientCredentialsFlow(t, id, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}) t.Cleanup(secretCleanup) @@ -517,8 +515,8 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with Like", func(t *testing.T) { - //secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) - //secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "bar"}}, nil) + // secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) + // secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "bar"}}, nil) id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() @@ -537,8 +535,8 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthAuthorization with Like", func(t *testing.T) { - //secret2, id1 := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_1", refreshTokenExpiryTime, nil) - //secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) + // secret2, id1 := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_1", refreshTokenExpiryTime, nil) + // secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() @@ -612,7 +610,7 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthAuthorizationCodeFlow with In", func(t *testing.T) { - //secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + // secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) id := testClientHelper().Ids.RandomSchemaObjectIdentifier() secret, secretCleanup := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id, integrationId, "foo", refreshTokenExpiryTime) From 34983afc46d8be0a08ca27c1a058de7d458ac888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 24 Sep 2024 14:40:37 +0200 Subject: [PATCH 28/34] updated generator README with validation issue for ConflictingFields validationType --- pkg/sdk/poc/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/sdk/poc/README.md b/pkg/sdk/poc/README.md index 44af1e130b..1bac4c2a02 100644 --- a/pkg/sdk/poc/README.md +++ b/pkg/sdk/poc/README.md @@ -132,6 +132,18 @@ type SomeReq struct { } ``` +- ConflictingFields validation results in: +```go +if everyValueSet(...) { + errs = append(errs, errOneOf(...)) +} + +// for now need to be changed manually to example bellow but should result in: +if moreThanOneValueSet(...) { + errs = append(errs, errMoreThanOneOf(...)) +} +``` + ##### Known limitations - automatic array conversion is not recursive, so we're only supporting one level mapping - []Request1{ foo Request2, bar int } won't be converted, but []Request1{ foo string, bar int } will From bdf2585574da6c6a5f77546015d0d107907aae1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 24 Sep 2024 14:40:59 +0200 Subject: [PATCH 29/34] updated after re-review --- pkg/sdk/secrets_validations_gen.go | 4 ++-- pkg/sdk/testint/secrets_gen_integration_test.go | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pkg/sdk/secrets_validations_gen.go b/pkg/sdk/secrets_validations_gen.go index b5f7e14800..f747d54ad7 100644 --- a/pkg/sdk/secrets_validations_gen.go +++ b/pkg/sdk/secrets_validations_gen.go @@ -76,8 +76,8 @@ func (opts *AlterSecretOptions) validate() error { errs = append(errs, errExactlyOneOf("AlterSecretOptions", "Set", "Unset")) } if valueSet(opts.Set) { - if everyValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { - errs = append(errs, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + if moreThanOneValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { + errs = append(errs, errMoreThanOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) } } return JoinErrors(errs...) diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 76df4308ef..5503f362ee 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -18,6 +18,8 @@ func TestInt_Secrets(t *testing.T) { ctx := testContext(t) integrationId := testClientHelper().Ids.RandomAccountObjectIdentifier() + + // "YYYY-MM-DD" or "YYYY-MM-DD HH-MI-SS" format has to be used, otherwise Snowflake returns error: "Invalid date/time format" refreshTokenExpiryTime := time.Now().Add(24 * time.Hour).Format(time.DateOnly) _, apiIntegrationCleanup := testClientHelper().SecurityIntegration.CreateApiAuthenticationClientCredentialsWithRequest(t, @@ -212,11 +214,11 @@ func TestInt_Secrets(t *testing.T) { require.NoError(t, err) t.Cleanup(testClientHelper().Secret.DropFunc(t, id)) - _, err = client.Secrets.ShowByID(ctx, id) + secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) assertions.AssertThat(t, - objectassert.Secret(t, id). + objectassert.SecretFromObject(t, secret). HasName(id.Name()). HasComment(comment). HasSecretType("PASSWORD"). @@ -535,9 +537,6 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthAuthorization with Like", func(t *testing.T) { - // secret2, id1 := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_1", refreshTokenExpiryTime, nil) - // secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) - id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() From 7791f33dae8de262967283156065ac9cee49972e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Wed, 25 Sep 2024 10:27:19 +0200 Subject: [PATCH 30/34] test changed to use errMoreThanOneOf --- pkg/sdk/secrets_gen_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 35a4a86988..4b591a7b7c 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -202,7 +202,7 @@ func TestSecrets_Alter(t *testing.T) { opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{OauthRefreshToken: String("foo"), OauthRefreshTokenExpiryTime: String("bar")} opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{Username: String("foo"), Password: String("bar")} opts.Set.SetForGenericString = &SetForGenericString{SecretString: String("secret")} - assertOptsInvalidJoinedErrors(t, opts, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + assertOptsInvalidJoinedErrors(t, opts, errMoreThanOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) }) t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { From d3e54db783bd43d49b0684e3b6b1c83b4672b628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 30 Sep 2024 14:32:31 +0200 Subject: [PATCH 31/34] Wrapped OAuth Scopes in separate queryStructField to allow empty list creation and alter set --- pkg/acceptance/helpers/secret_client.go | 3 +- pkg/sdk/secrets_def.go | 13 +++--- pkg/sdk/secrets_dto_builders_gen.go | 28 ++++++++---- pkg/sdk/secrets_dto_gen.go | 8 +++- pkg/sdk/secrets_gen.go | 7 ++- pkg/sdk/secrets_gen_integration_test.go | 43 ------------------- pkg/sdk/secrets_gen_test.go | 18 +++++--- pkg/sdk/secrets_impl_gen.go | 22 ++++++++-- .../testint/secrets_gen_integration_test.go | 37 +++++++--------- 9 files changed, 86 insertions(+), 93 deletions(-) delete mode 100644 pkg/sdk/secrets_gen_integration_test.go diff --git a/pkg/acceptance/helpers/secret_client.go b/pkg/acceptance/helpers/secret_client.go index f2657b39bb..74073b5389 100644 --- a/pkg/acceptance/helpers/secret_client.go +++ b/pkg/acceptance/helpers/secret_client.go @@ -28,7 +28,8 @@ func (c *SecretClient) client() sdk.Secrets { func (c *SecretClient) CreateWithOAuthClientCredentialsFlow(t *testing.T, id sdk.SchemaObjectIdentifier, apiIntegration sdk.AccountObjectIdentifier, oauthScopes []sdk.ApiIntegrationScope) (*sdk.Secret, func()) { t.Helper() ctx := context.Background() - request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, apiIntegration, oauthScopes) + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, apiIntegration). + WithOauthScopes(sdk.OauthScopesListRequest{oauthScopes}) err := c.client().CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index d4edb0494f..d816f19dcd 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -4,9 +4,6 @@ import g "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/gen //go:generate go run ./poc/main.go -var secretsApiIntegrationScopeDef = g.NewQueryStruct("ApiIntegrationScope"). - Text("Scope", g.KeywordOptions().SingleQuotes().Required()) - var secretDbRow = g.DbStruct("secretDBRow"). Field("created_on", "time.Time"). Field("name", "string"). @@ -57,12 +54,17 @@ var secretDetails = g.PlainStruct("SecretDetails"). Field("OauthScopes", "[]string"). Field("IntegrationName", "*string") +var secretsApiIntegrationScopeDef = g.NewQueryStruct("ApiIntegrationScope"). + Text("Scope", g.KeywordOptions().SingleQuotes().Required()) + +var oauthScopesListDef = g.NewQueryStruct("OauthScopesList").List("OauthScopesList", "ApiIntegrationScope", g.ListOptions().Required().MustParentheses()) + var secretSet = g.NewQueryStruct("SecretSet"). OptionalComment(). OptionalQueryStructField( "SetForOAuthClientCredentialsFlow", g.NewQueryStruct("SetForOAuthClientCredentialsFlow"). - ListAssignment("OAUTH_SCOPES", "ApiIntegrationScope", g.ParameterOptions().Parentheses().Required()), + OptionalQueryStructField("OauthScopes", oauthScopesListDef, g.ParameterOptions().SQL("OAUTH_SCOPES").Parentheses()), g.KeywordOptions(), ). OptionalQueryStructField( @@ -106,7 +108,7 @@ var SecretsDef = g.NewInterface( Name(). PredefinedQueryStructField("secretType", "string", g.StaticOptions().SQL("TYPE = OAUTH2")). Identifier("ApiIntegration", g.KindOfT[AccountObjectIdentifier](), g.IdentifierOptions().Required().Equals().SQL("API_AUTHENTICATION")). - ListAssignment("OAUTH_SCOPES", "ApiIntegrationScope", g.ParameterOptions().Parentheses().Required()). + OptionalQueryStructField("OauthScopes", oauthScopesListDef, g.ParameterOptions().SQL("OAUTH_SCOPES").Parentheses()). OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), @@ -127,7 +129,6 @@ var SecretsDef = g.NewInterface( OptionalComment(). WithValidation(g.ValidIdentifier, "name"). WithValidation(g.ConflictingFields, "OrReplace", "IfNotExists"), - secretsApiIntegrationScopeDef, ).CustomOperation( "CreateWithBasicAuthentication", "https://docs.snowflake.com/en/sql-reference/sql/create-secret", diff --git a/pkg/sdk/secrets_dto_builders_gen.go b/pkg/sdk/secrets_dto_builders_gen.go index 9faeabb35a..25eff46b72 100644 --- a/pkg/sdk/secrets_dto_builders_gen.go +++ b/pkg/sdk/secrets_dto_builders_gen.go @@ -7,12 +7,10 @@ import () func NewCreateWithOAuthClientCredentialsFlowSecretRequest( name SchemaObjectIdentifier, ApiIntegration AccountObjectIdentifier, - OauthScopes []ApiIntegrationScope, ) *CreateWithOAuthClientCredentialsFlowSecretRequest { s := CreateWithOAuthClientCredentialsFlowSecretRequest{} s.name = name s.ApiIntegration = ApiIntegration - s.OauthScopes = OauthScopes return &s } @@ -26,11 +24,24 @@ func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithIfNotExists(IfNo return s } +func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithOauthScopes(OauthScopes OauthScopesListRequest) *CreateWithOAuthClientCredentialsFlowSecretRequest { + s.OauthScopes = &OauthScopes + return s +} + func (s *CreateWithOAuthClientCredentialsFlowSecretRequest) WithComment(Comment string) *CreateWithOAuthClientCredentialsFlowSecretRequest { s.Comment = &Comment return s } +func NewOauthScopesListRequest( + OauthScopesList []ApiIntegrationScope, +) *OauthScopesListRequest { + s := OauthScopesListRequest{} + s.OauthScopesList = OauthScopesList + return &s +} + func NewCreateWithOAuthAuthorizationCodeFlowSecretRequest( name SchemaObjectIdentifier, OauthRefreshToken string, @@ -164,12 +175,13 @@ func (s *SecretSetRequest) WithSetForGenericString(SetForGenericString SetForGen return s } -func NewSetForOAuthClientCredentialsFlowRequest( - OauthScopes []ApiIntegrationScope, -) *SetForOAuthClientCredentialsFlowRequest { - s := SetForOAuthClientCredentialsFlowRequest{} - s.OauthScopes = OauthScopes - return &s +func NewSetForOAuthClientCredentialsFlowRequest() *SetForOAuthClientCredentialsFlowRequest { + return &SetForOAuthClientCredentialsFlowRequest{} +} + +func (s *SetForOAuthClientCredentialsFlowRequest) WithOauthScopes(OauthScopes OauthScopesListRequest) *SetForOAuthClientCredentialsFlowRequest { + s.OauthScopes = &OauthScopes + return s } func NewSetForOAuthAuthorizationFlowRequest() *SetForOAuthAuthorizationFlowRequest { diff --git a/pkg/sdk/secrets_dto_gen.go b/pkg/sdk/secrets_dto_gen.go index 3eec952bb4..656ca9ac69 100644 --- a/pkg/sdk/secrets_dto_gen.go +++ b/pkg/sdk/secrets_dto_gen.go @@ -18,10 +18,14 @@ type CreateWithOAuthClientCredentialsFlowSecretRequest struct { IfNotExists *bool name SchemaObjectIdentifier // required ApiIntegration AccountObjectIdentifier // required - OauthScopes []ApiIntegrationScope // required + OauthScopes *OauthScopesListRequest Comment *string } +type OauthScopesListRequest struct { + OauthScopesList []ApiIntegrationScope // required +} + type CreateWithOAuthAuthorizationCodeFlowSecretRequest struct { OrReplace *bool IfNotExists *bool @@ -65,7 +69,7 @@ type SecretSetRequest struct { } type SetForOAuthClientCredentialsFlowRequest struct { - OauthScopes []ApiIntegrationScope // required + OauthScopes *OauthScopesListRequest } type SetForOAuthAuthorizationFlowRequest struct { diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index 8a5a819e5f..db2d30df35 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -27,12 +27,15 @@ type CreateWithOAuthClientCredentialsFlowSecretOptions struct { name SchemaObjectIdentifier `ddl:"identifier"` secretType string `ddl:"static" sql:"TYPE = OAUTH2"` ApiIntegration AccountObjectIdentifier `ddl:"identifier,equals" sql:"API_AUTHENTICATION"` - OauthScopes []ApiIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` + OauthScopes *OauthScopesList `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"` } type ApiIntegrationScope struct { Scope string `ddl:"keyword,single_quotes"` } +type OauthScopesList struct { + OauthScopesList []ApiIntegrationScope `ddl:"list,must_parentheses"` +} // CreateWithOAuthAuthorizationCodeFlowSecretOptions is based on https://docs.snowflake.com/en/sql-reference/sql/create-secret. type CreateWithOAuthAuthorizationCodeFlowSecretOptions struct { @@ -90,7 +93,7 @@ type SecretSet struct { SetForGenericString *SetForGenericString `ddl:"keyword"` } type SetForOAuthClientCredentialsFlow struct { - OauthScopes []ApiIntegrationScope `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` + OauthScopes *OauthScopesList `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"` } type SetForOAuthAuthorizationFlow struct { OauthRefreshToken *string `ddl:"parameter,single_quotes" sql:"OAUTH_REFRESH_TOKEN"` diff --git a/pkg/sdk/secrets_gen_integration_test.go b/pkg/sdk/secrets_gen_integration_test.go deleted file mode 100644 index 4474555b36..0000000000 --- a/pkg/sdk/secrets_gen_integration_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package sdk - -import "testing" - -func TestInt_Secrets(t *testing.T) { - // TODO: prepare common resources - - t.Run("CreateWithOAuthClientCredentialsFlow", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("CreateWithBasicAuthentication", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("CreateWithGenericString", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Alter", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Drop", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Show", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("ShowByID", func(t *testing.T) { - // TODO: fill me - }) - - t.Run("Describe", func(t *testing.T) { - // TODO: fill me - }) -} diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 4b591a7b7c..486560c642 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -34,7 +34,7 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { opts := defaultOpts() opts.IfNotExists = Bool(true) opts.ApiIntegration = integration - opts.OauthScopes = []ApiIntegrationScope{{"test"}} + opts.OauthScopes = &OauthScopesList{[]ApiIntegrationScope{{"test"}}} opts.Comment = String("foo") assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = ('test') COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) @@ -45,9 +45,9 @@ func TestSecrets_CreateWithOAuthClientCredentialsFlow(t *testing.T) { opts := defaultOpts() opts.IfNotExists = Bool(true) opts.ApiIntegration = integration - opts.OauthScopes = []ApiIntegrationScope{} + opts.OauthScopes = &OauthScopesList{[]ApiIntegrationScope{}} opts.Comment = String("foo") - assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) + assertOptsValidAndSQLEquals(t, opts, "CREATE SECRET IF NOT EXISTS %s TYPE = OAUTH2 API_AUTHENTICATION = %s OAUTH_SCOPES = () COMMENT = 'foo'", id.FullyQualifiedName(), integration.FullyQualifiedName()) }) } @@ -198,7 +198,7 @@ func TestSecrets_Alter(t *testing.T) { t.Run("validation: conflicting fields for [opts.Set.SetForOAuthClientCredentialsFlow opts.Set.SetForOAuthAuthorizationFlow opts.Set.SetForBasicAuthentication opts.Set.SetForGenericString]", func(t *testing.T) { opts := setOpts() - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{{Scope: "foo"}}} + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: &OauthScopesList{[]ApiIntegrationScope{{Scope: "foo"}}}} opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{OauthRefreshToken: String("foo"), OauthRefreshTokenExpiryTime: String("bar")} opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{Username: String("foo"), Password: String("bar")} opts.Set.SetForGenericString = &SetForGenericString{SecretString: String("secret")} @@ -208,14 +208,20 @@ func TestSecrets_Alter(t *testing.T) { t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { opts := setOpts() opts.Set.Comment = String("test") - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{{"sample_scope"}}} + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: &OauthScopesList{[]ApiIntegrationScope{{"sample_scope"}}}} assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_SCOPES = ('sample_scope')", id.FullyQualifiedName()) }) t.Run("alter: set options for Oauth Client Credentials Flow - empty oauth scopes list", func(t *testing.T) { opts := setOpts() opts.Set.Comment = String("test") - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: []ApiIntegrationScope{}} + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{OauthScopes: &OauthScopesList{}} + assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test' OAUTH_SCOPES = ()", id.FullyQualifiedName()) + }) + + t.Run("alter: set options for Oauth Client Credentials Flow - without oauth scopes provided", func(t *testing.T) { + opts := setOpts() + opts.Set.Comment = String("test") assertOptsValidAndSQLEquals(t, opts, "ALTER SECRET IF EXISTS %s SET COMMENT = 'test'", id.FullyQualifiedName()) }) diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index 4464553f9a..89e7796c0a 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -79,9 +79,18 @@ func (r *CreateWithOAuthClientCredentialsFlowSecretRequest) toOpts() *CreateWith IfNotExists: r.IfNotExists, name: r.name, ApiIntegration: r.ApiIntegration, - OauthScopes: r.OauthScopes, - Comment: r.Comment, + + Comment: r.Comment, } + + if r.OauthScopes != nil { + + opts.OauthScopes = &OauthScopesList{ + OauthScopesList: r.OauthScopes.OauthScopesList, + } + + } + return opts } @@ -133,8 +142,13 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { } if r.Set.SetForOAuthClientCredentialsFlow != nil { - opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{ - OauthScopes: r.Set.SetForOAuthClientCredentialsFlow.OauthScopes, + opts.Set.SetForOAuthClientCredentialsFlow = &SetForOAuthClientCredentialsFlow{} + + if r.Set.SetForOAuthClientCredentialsFlow.OauthScopes != nil { + opts.Set.SetForOAuthClientCredentialsFlow.OauthScopes = &OauthScopesList{ + OauthScopesList: r.Set.SetForOAuthClientCredentialsFlow.OauthScopes.OauthScopesList, + } + } } diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index 5503f362ee..5e845368db 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -63,7 +63,8 @@ func TestInt_Secrets(t *testing.T) { t.Run("Create: secretWithOAuthClientCredentialsFlow", func(t *testing.T) { id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}). + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId). + WithOauthScopes(sdk.OauthScopesListRequest{OauthScopesList: []sdk.ApiIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}}). WithComment("a"). WithIfNotExists(true) @@ -93,11 +94,11 @@ func TestInt_Secrets(t *testing.T) { }) }) - // It is possible to create secret without specifying both refresh token properties and scopes - // Scopes are not being inherited from the security_integration what is tested further + // It is possible to create secret without specifying both refresh token properties and OAuth scopes + // Regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret with empty oauth_scopes list should inherit scopes from security_integration, but it does not t.Run("Create: secretWithOAuth - minimal, without token and scopes", func(t *testing.T) { id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, nil) + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId) err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) @@ -123,7 +124,7 @@ func TestInt_Secrets(t *testing.T) { // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret with empty oauth_scopes list should inherit scopes from security_integration, but it does not t.Run("Create: SecretWithOAuthClientCredentialsFlow - Empty Scopes List", func(t *testing.T) { id := testClientHelper().Ids.RandomSchemaObjectIdentifier() - request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId, []sdk.ApiIntegrationScope{}) + request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, integrationId).WithOauthScopes(sdk.OauthScopesListRequest{}) err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) @@ -145,7 +146,7 @@ func TestInt_Secrets(t *testing.T) { assert.NotContains(t, details.OauthScopes, "foo") assert.NotContains(t, details.OauthScopes, "bar") - assert.Empty(t, details.OauthScopes) + assert.Equal(t, []string{""}, details.OauthScopes) }) t.Run("Create: SecretWithOAuthAuthorizationCodeFlow - refreshTokenExpiry date format", func(t *testing.T) { @@ -308,9 +309,8 @@ func TestInt_Secrets(t *testing.T) { *sdk.NewSecretSetRequest(). WithComment(comment). WithSetForOAuthClientCredentialsFlow( - *sdk.NewSetForOAuthClientCredentialsFlowRequest( - []sdk.ApiIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}, - ), + *sdk.NewSetForOAuthClientCredentialsFlowRequest(). + WithOauthScopes(sdk.OauthScopesListRequest{OauthScopesList: []sdk.ApiIntegrationScope{{Scope: "foo"}, {Scope: "bar"}}}), ), ) err := client.Secrets.Alter(ctx, setRequest) @@ -450,24 +450,23 @@ func TestInt_Secrets(t *testing.T) { err := client.Secrets.Alter(ctx, setRequest) require.NoError(t, err) + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + // Cannot assert secret string because snowflake does not output its value neither with SHOW nor DESCRIBE + assert.Equal(t, comment, *details.Comment) + unsetRequest := sdk.NewAlterSecretRequest(id). WithUnset( *sdk.NewSecretUnsetRequest(). WithComment(true), ) - err = client.Secrets.Alter(ctx, unsetRequest) require.NoError(t, err) - details, err := client.Secrets.Describe(ctx, id) + details, err = client.Secrets.Describe(ctx, id) require.NoError(t, err) - assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "GENERIC_STRING", - Comment: nil, - }) - assert.Empty(t, details.Comment) }) @@ -517,8 +516,6 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthClientCredentialsFlow with Like", func(t *testing.T) { - // secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "foo"}}, nil) - // secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.ApiIntegrationScope{{Scope: "bar"}}, nil) id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() id2 := testClientHelper().Ids.RandomSchemaObjectIdentifier() @@ -609,8 +606,6 @@ func TestInt_Secrets(t *testing.T) { }) t.Run("Show: SecretWithOAuthAuthorizationCodeFlow with In", func(t *testing.T) { - // secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) - id := testClientHelper().Ids.RandomSchemaObjectIdentifier() secret, secretCleanup := testClientHelper().Secret.CreateWithOAuthAuthorizationCodeFlow(t, id, integrationId, "foo", refreshTokenExpiryTime) t.Cleanup(secretCleanup) From 0e181360fceab0b55bdadc37a4822102200908d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 30 Sep 2024 14:35:20 +0200 Subject: [PATCH 32/34] Linter adjustments --- pkg/acceptance/helpers/secret_client.go | 2 +- pkg/sdk/secrets_impl_gen.go | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/acceptance/helpers/secret_client.go b/pkg/acceptance/helpers/secret_client.go index 74073b5389..e3eb87c8f1 100644 --- a/pkg/acceptance/helpers/secret_client.go +++ b/pkg/acceptance/helpers/secret_client.go @@ -29,7 +29,7 @@ func (c *SecretClient) CreateWithOAuthClientCredentialsFlow(t *testing.T, id sdk t.Helper() ctx := context.Background() request := sdk.NewCreateWithOAuthClientCredentialsFlowSecretRequest(id, apiIntegration). - WithOauthScopes(sdk.OauthScopesListRequest{oauthScopes}) + WithOauthScopes(sdk.OauthScopesListRequest{OauthScopesList: oauthScopes}) err := c.client().CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) diff --git a/pkg/sdk/secrets_impl_gen.go b/pkg/sdk/secrets_impl_gen.go index 89e7796c0a..f6804181f0 100644 --- a/pkg/sdk/secrets_impl_gen.go +++ b/pkg/sdk/secrets_impl_gen.go @@ -84,11 +84,9 @@ func (r *CreateWithOAuthClientCredentialsFlowSecretRequest) toOpts() *CreateWith } if r.OauthScopes != nil { - opts.OauthScopes = &OauthScopesList{ OauthScopesList: r.OauthScopes.OauthScopesList, } - } return opts @@ -148,7 +146,6 @@ func (r *AlterSecretRequest) toOpts() *AlterSecretOptions { opts.Set.SetForOAuthClientCredentialsFlow.OauthScopes = &OauthScopesList{ OauthScopesList: r.Set.SetForOAuthClientCredentialsFlow.OauthScopes.OauthScopesList, } - } } From a18b8f59fb9a22f523103e577aefe35cddf90835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Mon, 30 Sep 2024 16:00:55 +0200 Subject: [PATCH 33/34] errMoreThanOneOf change to be proper errOneOf --- pkg/sdk/poc/README.md | 4 ++-- pkg/sdk/secrets_gen_test.go | 2 +- pkg/sdk/secrets_validations_gen.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/sdk/poc/README.md b/pkg/sdk/poc/README.md index 1bac4c2a02..f01d7ceed2 100644 --- a/pkg/sdk/poc/README.md +++ b/pkg/sdk/poc/README.md @@ -135,12 +135,12 @@ type SomeReq struct { - ConflictingFields validation results in: ```go if everyValueSet(...) { - errs = append(errs, errOneOf(...)) + ... } // for now need to be changed manually to example bellow but should result in: if moreThanOneValueSet(...) { - errs = append(errs, errMoreThanOneOf(...)) + ... } ``` diff --git a/pkg/sdk/secrets_gen_test.go b/pkg/sdk/secrets_gen_test.go index 486560c642..458d505af0 100644 --- a/pkg/sdk/secrets_gen_test.go +++ b/pkg/sdk/secrets_gen_test.go @@ -202,7 +202,7 @@ func TestSecrets_Alter(t *testing.T) { opts.Set.SetForOAuthAuthorizationFlow = &SetForOAuthAuthorizationFlow{OauthRefreshToken: String("foo"), OauthRefreshTokenExpiryTime: String("bar")} opts.Set.SetForBasicAuthentication = &SetForBasicAuthentication{Username: String("foo"), Password: String("bar")} opts.Set.SetForGenericString = &SetForGenericString{SecretString: String("secret")} - assertOptsInvalidJoinedErrors(t, opts, errMoreThanOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + assertOptsInvalidJoinedErrors(t, opts, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) }) t.Run("alter: set options for Oauth Client Credentials Flow", func(t *testing.T) { diff --git a/pkg/sdk/secrets_validations_gen.go b/pkg/sdk/secrets_validations_gen.go index f747d54ad7..a324b74dee 100644 --- a/pkg/sdk/secrets_validations_gen.go +++ b/pkg/sdk/secrets_validations_gen.go @@ -77,7 +77,7 @@ func (opts *AlterSecretOptions) validate() error { } if valueSet(opts.Set) { if moreThanOneValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { - errs = append(errs, errMoreThanOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + errs = append(errs, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) } } return JoinErrors(errs...) From bbd7b7a3af71482cf33b437961aa15dbf2cc3a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Tue, 1 Oct 2024 10:07:14 +0200 Subject: [PATCH 34/34] readme known issues more verbose description of the issue --- pkg/sdk/poc/README.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/pkg/sdk/poc/README.md b/pkg/sdk/poc/README.md index f01d7ceed2..28786b72d7 100644 --- a/pkg/sdk/poc/README.md +++ b/pkg/sdk/poc/README.md @@ -132,15 +132,26 @@ type SomeReq struct { } ``` -- ConflictingFields validation results in: +- Wrong generated validations for `ConflictingFields` for more complicated validations + - For now `everyValueSet()` should be manually changed to `moreThanOneValueSet()` if there is a need to validate only one of many options + - Consider following example for `secret`: ```go -if everyValueSet(...) { - ... +// For validation Conflicting fields: +WithValidation(g.ConflictingFields, "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString") +``` +```go +// Generation results in: +if valueSet(opts.Set) { + if everyValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { + errs = append(errs, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + } } -// for now need to be changed manually to example bellow but should result in: -if moreThanOneValueSet(...) { - ... +// For now needs to be manually changed to: +if valueSet(opts.Set) { + if moreThanOneValueSet(opts.Set.SetForOAuthClientCredentialsFlow, opts.Set.SetForOAuthAuthorizationFlow, opts.Set.SetForBasicAuthentication, opts.Set.SetForGenericString) { + errs = append(errs, errOneOf("AlterSecretOptions.Set", "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString")) + } } ```