Skip to content

Commit

Permalink
chore: Generate ID and ObjectType Show Object Methods (#3292)
Browse files Browse the repository at this point in the history
<!-- Feel free to delete comments as you fill this in -->

<!-- summary of changes -->
## Changes
* added generating ID() and ObjectType() helper methods

## Examples
Generated examples for:
**SchemaObjectIdentifier**
* secrets
* streamlits

**AccountObjectIdentifier**
* api_integrations
* notificatoin_integrations
  • Loading branch information
sfc-gh-fbudzynski authored and sfc-gh-jcieslak committed Jan 20, 2025
1 parent acb93de commit 8dbf002
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 11 deletions.
27 changes: 26 additions & 1 deletion pkg/sdk/poc/generator/interface.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
package generator

import "fmt"

type objectIdentifierKind string

const (
AccountObjectIdentifier objectIdentifierKind = "AccountObjectIdentifier"
DatabaseObjectIdentifier objectIdentifierKind = "DatabaseObjectIdentifier"
SchemaObjectIdentifier objectIdentifierKind = "SchemaObjectIdentifier"
SchemaObjectIdentifierWithArguments objectIdentifierKind = "SchemaObjectIdentifierWithArguments"
)

func toObjectIdentifierKind(s string) (objectIdentifierKind, error) {
switch s {
case "AccountObjectIdentifier":
return AccountObjectIdentifier, nil
case "DatabaseObjectIdentifier":
return DatabaseObjectIdentifier, nil
case "SchemaObjectIdentifier":
return SchemaObjectIdentifier, nil
case "SchemaObjectIdentifierWithArguments":
return SchemaObjectIdentifierWithArguments, nil
default:
return "", fmt.Errorf("invalid string identifier type: %s", s)
}
}

// Interface groups operations for particular object or objects family (e.g. DATABASE ROLE)
type Interface struct {
// Name is the interface's name, e.g. "DatabaseRoles"
Expand Down Expand Up @@ -28,6 +54,5 @@ func (i *Interface) NameLowerCased() string {

// ObjectIdentifierKind returns the level of the object identifier (e.g. for DatabaseObjectIdentifier, it returns the prefix "Database")
func (i *Interface) ObjectIdentifierPrefix() idPrefix {
// return strings.Replace(i.IdentifierKind, "ObjectIdentifier", "", 1)
return identifierStringToPrefix(i.IdentifierKind)
}
11 changes: 8 additions & 3 deletions pkg/sdk/poc/generator/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ func (s *Operation) withHelperStructs(helperStructs ...*Field) *Operation {
return s
}

func (s *Operation) withObjectInterface(objectInterface *Interface) *Operation {
s.ObjectInterface = objectInterface
return s
}

func addShowMapping(op *Operation, from, to *Field) {
op.ShowMapping = newMapping("convert", from, to)
}
Expand Down Expand Up @@ -170,9 +175,9 @@ func (i *Interface) ShowByIdOperationWithNoFiltering() *Interface {

// ShowByIdOperationWithFiltering adds a ShowByID operation to the interface with filtering. Should be used for objects that implement filtering options e.g. Like or In.
func (i *Interface) ShowByIdOperationWithFiltering(filter ShowByIDFilteringKind, filtering ...ShowByIDFilteringKind) *Interface {
op := newNoSqlOperation(string(OperationKindShowByID))
op.ObjectInterface = i
op.withFiltering(append([]ShowByIDFilteringKind{filter}, filtering...)...)
op := newNoSqlOperation(string(OperationKindShowByID)).
withObjectInterface(i).
withFiltering(append(filtering, filter)...)
i.Operations = append(i.Operations, op)
return i
}
Expand Down
60 changes: 60 additions & 0 deletions pkg/sdk/poc/generator/show_object_methods.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package generator

import (
"log"
"slices"
)

type ShowObjectIdMethod struct {
StructName string
IdentifierKind objectIdentifierKind
Args []string
}

func newShowObjectIDMethod(structName string, idType objectIdentifierKind) *ShowObjectIdMethod {
return &ShowObjectIdMethod{
StructName: structName,
IdentifierKind: idType,
Args: idTypeParts[idType],
}
}

var idTypeParts map[objectIdentifierKind][]string = map[objectIdentifierKind][]string{
AccountObjectIdentifier: {"Name"},
DatabaseObjectIdentifier: {"DatabaseName", "Name"},
SchemaObjectIdentifier: {"DatabaseName", "SchemaName", "Name"},
}

func checkRequiredFieldsForIdMethod(structName string, helperStructs []*Field, idKind objectIdentifierKind) bool {
if requiredFields, ok := idTypeParts[idKind]; ok {
for _, field := range helperStructs {
if field.Name == structName {
return containsFieldNames(field.Fields, requiredFields...)
}
}
}
log.Printf("[WARN] no required fields mapping defined for identifier %s", idKind)
return false
}

func containsFieldNames(fields []*Field, names ...string) bool {
fieldNames := []string{}
for _, field := range fields {
fieldNames = append(fieldNames, field.Name)
}

for _, name := range names {
if !slices.Contains(fieldNames, name) {
return false
}
}
return true
}

type ShowObjectTypeMethod struct {
StructName string
}

func newShowObjectTypeMethod(structName string) *ShowObjectTypeMethod {
return &ShowObjectTypeMethod{StructName: structName}
}
50 changes: 50 additions & 0 deletions pkg/sdk/poc/generator/show_object_methods_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package generator

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestIdentifierStringToObjectIdentifier(t *testing.T) {
tests := []struct {
input string
expected objectIdentifierKind
}{
{"AccountObjectIdentifier", AccountObjectIdentifier},
{"DatabaseObjectIdentifier", DatabaseObjectIdentifier},
{"SchemaObjectIdentifier", SchemaObjectIdentifier},
{"SchemaObjectIdentifierWithArguments", SchemaObjectIdentifierWithArguments},
}

for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
result, err := toObjectIdentifierKind(test.input)
require.NoError(t, err)
require.Equal(t, test.expected, result)
})
}
}

func TestIdentifierStringToObjectIdentifier_Invalid(t *testing.T) {
tests := []struct {
input string
err string
}{
{"accountobjectidentifier", "invalid string identifier type: accountobjectidentifier"},
{"Account", "invalid string identifier type: Account"},
{"databaseobjectidentifier", "invalid string identifier type: databaseobjectidentifier"},
{"Database", "invalid string identifier type: Database"},
{"schemaobjectidentifier", "invalid string identifier type: schemaobjectidentifier"},
{"Schema", "invalid string identifier type: Schema"},
{"schemaobjectidentifierwitharguments", "invalid string identifier type: schemaobjectidentifierwitharguments"},
{"schemawitharguemnts", "invalid string identifier type: schemawitharguemnts"},
}

for _, tc := range tests {
t.Run(tc.input, func(t *testing.T) {
_, err := toObjectIdentifierKind(tc.input)
require.ErrorContains(t, err, tc.err)
})
}
}
20 changes: 20 additions & 0 deletions pkg/sdk/poc/generator/template_executors.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,29 @@ func GenerateInterface(writer io.Writer, def *Interface) {
if o.OptsField != nil {
generateOptionsStruct(writer, o)
}

if o.Name == string(OperationKindShow) {
idKind, err := toObjectIdentifierKind(def.IdentifierKind)
if err != nil {
log.Printf("[WARN] for showObjectIdMethod: %v", err)
}
if checkRequiredFieldsForIdMethod(def.NameSingular, o.HelperStructs, idKind) {
generateShowObjectIdMethod(writer, newShowObjectIDMethod(def.NameSingular, idKind))
}

generateShowObjectTypeMethod(writer, newShowObjectTypeMethod(def.NameSingular))
}
}
}

func generateShowObjectIdMethod(writer io.Writer, m *ShowObjectIdMethod) {
printTo(writer, ShowObjectIdMethodTemplate, m)
}

func generateShowObjectTypeMethod(writer io.Writer, m *ShowObjectTypeMethod) {
printTo(writer, ShowObjectTypeMethodTemplate, m)
}

func generateOptionsStruct(writer io.Writer, operation *Operation) {
printTo(writer, OperationStructTemplate, operation)

Expand Down
8 changes: 8 additions & 0 deletions pkg/sdk/poc/generator/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ var (
structTemplateContent string
StructTemplate, _ = template.New("structTemplate").Parse(structTemplateContent)

//go:embed templates/show_object_id_method.tmpl
showObjectIdMethodTemplateContent string
ShowObjectIdMethodTemplate, _ = template.New("showObjectIdMethodTemplate").Parse(showObjectIdMethodTemplateContent)

//go:embed templates/show_object_type_method.tmpl
showObjectTypeMethodTemplateContent string
ShowObjectTypeMethodTemplate, _ = template.New("showObjectTypeMethodTemplate").Parse(showObjectTypeMethodTemplateContent)

//go:embed templates/dto_declarations.tmpl
dtoDeclarationsTemplateContent string
DtoTemplate, _ = template.New("dtoTemplate").Parse(dtoDeclarationsTemplateContent)
Expand Down
5 changes: 5 additions & 0 deletions pkg/sdk/poc/generator/templates/show_object_id_method.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{- /*gotype: github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/generator.ShowObjectIdMethod*/ -}}

func (v *{{ .StructName }}) ID() {{ .IdentifierKind }} {
return New{{ .IdentifierKind }}({{ range .Args }}v.{{ . }}, {{ end }})
}
5 changes: 5 additions & 0 deletions pkg/sdk/poc/generator/templates/show_object_type_method.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{- /*gotype: github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/poc/generator.ShowObjectTypeMethod*/ -}}

func (v *{{ .StructName }}) ObjectType() ObjectType {
return ObjectType{{ .StructName }}
}
17 changes: 14 additions & 3 deletions pkg/sdk/secrets_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ type CreateWithOAuthClientCredentialsFlowSecretOptions struct {
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"`
}
Expand Down Expand Up @@ -85,30 +87,37 @@ type AlterSecretOptions struct {
Set *SecretSet `ddl:"keyword" sql:"SET"`
Unset *SecretUnset `ddl:"keyword"`
}

type SecretSet struct {
Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"`
SetForFlow *SetForFlow `ddl:"keyword"`
}

type SetForFlow struct {
SetForOAuthClientCredentials *SetForOAuthClientCredentials `ddl:"keyword"`
SetForOAuthAuthorization *SetForOAuthAuthorization `ddl:"keyword"`
SetForBasicAuthentication *SetForBasicAuthentication `ddl:"keyword"`
SetForGenericString *SetForGenericString `ddl:"keyword"`
}

type SetForOAuthClientCredentials struct {
OauthScopes *OauthScopesList `ddl:"parameter,parentheses" sql:"OAUTH_SCOPES"`
}

type SetForOAuthAuthorization 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 {
Comment *bool `ddl:"keyword" sql:"SET COMMENT = NULL"`
}
Expand All @@ -128,6 +137,7 @@ type ShowSecretOptions struct {
Like *Like `ddl:"keyword" sql:"LIKE"`
In *ExtendedIn `ddl:"keyword" sql:"IN"`
}

type secretDBRow struct {
CreatedOn time.Time `db:"created_on"`
Name string `db:"name"`
Expand All @@ -139,6 +149,7 @@ type secretDBRow struct {
OauthScopes sql.NullString `db:"oauth_scopes"`
OwnerRoleType string `db:"owner_role_type"`
}

type Secret struct {
CreatedOn time.Time
Name string
Expand All @@ -151,11 +162,11 @@ type Secret struct {
OwnerRoleType string
}

func (s *Secret) ID() SchemaObjectIdentifier {
return NewSchemaObjectIdentifier(s.DatabaseName, s.SchemaName, s.Name)
func (v *Secret) ID() SchemaObjectIdentifier {
return NewSchemaObjectIdentifier(v.DatabaseName, v.SchemaName, v.Name)
}

func (s *Secret) ObjectType() ObjectType {
func (v *Secret) ObjectType() ObjectType {
return ObjectTypeSecret
}

Expand Down
15 changes: 11 additions & 4 deletions pkg/sdk/streamlits_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type CreateStreamlitOptions struct {
Title *string `ddl:"parameter,single_quotes" sql:"TITLE"`
Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"`
}

type ExternalAccessIntegrations struct {
ExternalAccessIntegrations []AccountObjectIdentifier `ddl:"list,must_parentheses"`
}
Expand All @@ -42,6 +43,7 @@ type AlterStreamlitOptions struct {
Unset *StreamlitUnset `ddl:"list,no_parentheses" sql:"UNSET"`
RenameTo *SchemaObjectIdentifier `ddl:"identifier" sql:"RENAME TO"`
}

type StreamlitSet struct {
RootLocation *string `ddl:"parameter,single_quotes" sql:"ROOT_LOCATION"`
MainFile *string `ddl:"parameter,single_quotes" sql:"MAIN_FILE"`
Expand All @@ -50,6 +52,7 @@ type StreamlitSet struct {
Comment *string `ddl:"parameter,single_quotes" sql:"COMMENT"`
Title *string `ddl:"parameter,single_quotes" sql:"TITLE"`
}

type StreamlitUnset struct {
QueryWarehouse *bool `ddl:"keyword" sql:"QUERY_WAREHOUSE"`
Comment *bool `ddl:"keyword" sql:"COMMENT"`
Expand All @@ -73,6 +76,7 @@ type ShowStreamlitOptions struct {
In *In `ddl:"keyword" sql:"IN"`
Limit *LimitFrom `ddl:"keyword" sql:"LIMIT"`
}

type streamlitsRow struct {
CreatedOn string `db:"created_on"`
Name string `db:"name"`
Expand All @@ -85,6 +89,7 @@ type streamlitsRow struct {
UrlId string `db:"url_id"`
OwnerRoleType string `db:"owner_role_type"`
}

type Streamlit struct {
CreatedOn string
Name string
Expand All @@ -98,12 +103,17 @@ type Streamlit struct {
OwnerRoleType string
}

func (v *Streamlit) ID() SchemaObjectIdentifier {
return NewSchemaObjectIdentifier(v.DatabaseName, v.SchemaName, v.Name)
}

// DescribeStreamlitOptions is based on https://docs.snowflake.com/en/sql-reference/sql/desc-streamlit.
type DescribeStreamlitOptions struct {
describe bool `ddl:"static" sql:"DESCRIBE"`
streamlit bool `ddl:"static" sql:"STREAMLIT"`
name SchemaObjectIdentifier `ddl:"identifier"`
}

type streamlitsDetailRow struct {
Name string `db:"name"`
Title sql.NullString `db:"title"`
Expand All @@ -117,6 +127,7 @@ type streamlitsDetailRow struct {
ExternalAccessIntegrations string `db:"external_access_integrations"`
ExternalAccessSecrets string `db:"external_access_secrets"`
}

type StreamlitDetail struct {
Name string
Title string
Expand All @@ -130,7 +141,3 @@ type StreamlitDetail struct {
ExternalAccessIntegrations []string
ExternalAccessSecrets string
}

func (s *Streamlit) ID() SchemaObjectIdentifier {
return NewSchemaObjectIdentifier(s.DatabaseName, s.SchemaName, s.Name)
}

0 comments on commit 8dbf002

Please sign in to comment.