Skip to content

Commit

Permalink
Add missing to procedure
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-asawicki committed Dec 12, 2024
1 parent 0c8e214 commit af4fb22
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -500,13 +500,11 @@ func (f *FunctionDetailsAssert) ContainsExactlySecrets(secrets map[string]sdk.Sc
for k, v := range secrets {
if s, ok := o.NormalizedSecrets[k]; !ok {
return fmt.Errorf("expected normalized secrets to have a secret associated with key %s", k)
} else {
if s.FullyQualifiedName() != v.FullyQualifiedName() {
return fmt.Errorf("expected secret with key %s to have id %s, got %s", k, v.FullyQualifiedName(), s.FullyQualifiedName())
}
} else if s.FullyQualifiedName() != v.FullyQualifiedName() {
return fmt.Errorf("expected secret with key %s to have id %s, got %s", k, v.FullyQualifiedName(), s.FullyQualifiedName())
}
}
for k, _ := range o.NormalizedSecrets {
for k := range o.NormalizedSecrets {
if _, ok := secrets[k]; !ok {
return fmt.Errorf("normalized secrets have unexpected key: %s", k)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,13 +486,11 @@ func (f *ProcedureDetailsAssert) ContainsExactlySecrets(secrets map[string]sdk.S
for k, v := range secrets {
if s, ok := o.NormalizedSecrets[k]; !ok {
return fmt.Errorf("expected normalized secrets to have a secret associated with key %s", k)
} else {
if s.FullyQualifiedName() != v.FullyQualifiedName() {
return fmt.Errorf("expected secret with key %s to have id %s, got %s", k, v.FullyQualifiedName(), s.FullyQualifiedName())
}
} else if s.FullyQualifiedName() != v.FullyQualifiedName() {
return fmt.Errorf("expected secret with key %s to have id %s, got %s", k, v.FullyQualifiedName(), s.FullyQualifiedName())
}
}
for k, _ := range o.NormalizedSecrets {
for k := range o.NormalizedSecrets {
if _, ok := secrets[k]; !ok {
return fmt.Errorf("normalized secrets have unexpected key: %s", k)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (f *FunctionJavaModel) WithExternalAccessIntegrations(ids ...sdk.AccountObj
}

func (f *FunctionJavaModel) WithSecrets(secrets map[string]sdk.SchemaObjectIdentifier) *FunctionJavaModel {
var objects []tfconfig.Variable
objects := make([]tfconfig.Variable, 0)
for k, v := range secrets {
objects = append(objects, tfconfig.ObjectVariable(
map[string]tfconfig.Variable{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package model
import (
"encoding/json"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/collections"

tfconfig "github.com/hashicorp/terraform-plugin-testing/config"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
Expand Down Expand Up @@ -77,6 +79,55 @@ func (f *ProcedureJavaModel) WithImport(stageLocation string, pathOnStage string
)
}

func (f *ProcedureJavaModel) WithImports(imports ...sdk.NormalizedPath) *ProcedureJavaModel {
return f.WithImportsValue(
tfconfig.SetVariable(
collections.Map(imports, func(imp sdk.NormalizedPath) tfconfig.Variable {
return tfconfig.ObjectVariable(
map[string]tfconfig.Variable{
"stage_location": tfconfig.StringVariable(imp.StageLocation),
"path_on_stage": tfconfig.StringVariable(imp.PathOnStage),
},
)
})...,
),
)
}

func (f *ProcedureJavaModel) WithPackages(pkgs ...string) *ProcedureJavaModel {
return f.WithPackagesValue(
tfconfig.SetVariable(
collections.Map(pkgs, func(pkg string) tfconfig.Variable { return tfconfig.StringVariable(pkg) })...,
),
)
}

func (f *ProcedureJavaModel) WithExternalAccessIntegrations(ids ...sdk.AccountObjectIdentifier) *ProcedureJavaModel {
return f.WithExternalAccessIntegrationsValue(
tfconfig.SetVariable(
collections.Map(ids, func(id sdk.AccountObjectIdentifier) tfconfig.Variable { return tfconfig.StringVariable(id.Name()) })...,
),
)
}

func (f *ProcedureJavaModel) WithSecrets(secrets map[string]sdk.SchemaObjectIdentifier) *ProcedureJavaModel {
objects := make([]tfconfig.Variable, 0)
for k, v := range secrets {
objects = append(objects, tfconfig.ObjectVariable(
map[string]tfconfig.Variable{
"secret_variable_name": tfconfig.StringVariable(k),
"secret_id": tfconfig.StringVariable(v.FullyQualifiedName()),
},
))
}

return f.WithSecretsValue(
tfconfig.SetVariable(
objects...,
),
)
}

func (f *ProcedureJavaModel) WithTargetPathParts(stageLocation string, pathOnStage string) *ProcedureJavaModel {
return f.WithTargetPathValue(
tfconfig.ObjectVariable(
Expand Down
48 changes: 48 additions & 0 deletions pkg/resources/function_and_procedure_commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,51 @@ func readFunctionOrProcedureTargetPath(d *schema.ResourceData, normalizedPath *s
}
return d.Set("target_path", tp)
}

func setExternalAccessIntegrationsInBuilder[T any](d *schema.ResourceData, setIntegrations func([]sdk.AccountObjectIdentifier) T) error {
integrations, err := parseExternalAccessIntegrationsCommon(d)
if err != nil {
return err
}
setIntegrations(integrations)
return nil
}

func setSecretsInBuilder[T any](d *schema.ResourceData, setSecrets func([]sdk.SecretReference) T) error {
secrets, err := parseSecretsCommon(d)
if err != nil {
return err
}
setSecrets(secrets)
return nil
}

func parseExternalAccessIntegrationsCommon(d *schema.ResourceData) ([]sdk.AccountObjectIdentifier, error) {
integrations := make([]sdk.AccountObjectIdentifier, 0)
if v, ok := d.GetOk("external_access_integrations"); ok {
for _, i := range v.(*schema.Set).List() {
id, err := sdk.ParseAccountObjectIdentifier(i.(string))
if err != nil {
return nil, err
}
integrations = append(integrations, id)
}
}
return integrations, nil
}

func parseSecretsCommon(d *schema.ResourceData) ([]sdk.SecretReference, error) {
secretReferences := make([]sdk.SecretReference, 0)
if v, ok := d.GetOk("secrets"); ok {
for _, s := range v.(*schema.Set).List() {
name := s.(map[string]any)["secret_variable_name"].(string)
idRaw := s.(map[string]any)["secret_id"].(string)
id, err := sdk.ParseSchemaObjectIdentifier(idRaw)
if err != nil {
return nil, err
}
secretReferences = append(secretReferences, sdk.SecretReference{VariableName: name, Name: id})
}
}
return secretReferences, nil
}
48 changes: 0 additions & 48 deletions pkg/resources/function_commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,36 +450,6 @@ func parseFunctionPackagesCommon(d *schema.ResourceData) ([]sdk.FunctionPackageR
return packages, nil
}

func parseExternalAccessIntegrationsCommon(d *schema.ResourceData) ([]sdk.AccountObjectIdentifier, error) {
integrations := make([]sdk.AccountObjectIdentifier, 0)
if v, ok := d.GetOk("external_access_integrations"); ok {
for _, i := range v.(*schema.Set).List() {
id, err := sdk.ParseAccountObjectIdentifier(i.(string))
if err != nil {
return nil, err
}
integrations = append(integrations, id)
}
}
return integrations, nil
}

func parseSecretsCommon(d *schema.ResourceData) ([]sdk.SecretReference, error) {
secretReferences := make([]sdk.SecretReference, 0)
if v, ok := d.GetOk("secrets"); ok {
for _, s := range v.(*schema.Set).List() {
name := s.(map[string]any)["secret_variable_name"].(string)
idRaw := s.(map[string]any)["secret_id"].(string)
id, err := sdk.ParseSchemaObjectIdentifier(idRaw)
if err != nil {
return nil, err
}
secretReferences = append(secretReferences, sdk.SecretReference{VariableName: name, Name: id})
}
}
return secretReferences, nil
}

func parseFunctionTargetPathCommon(d *schema.ResourceData) (string, error) {
var tp string
if v, ok := d.GetOk("target_path"); ok {
Expand Down Expand Up @@ -530,24 +500,6 @@ func setFunctionPackagesInBuilder[T any](d *schema.ResourceData, setPackages fun
return nil
}

func setExternalAccessIntegrationsInBuilder[T any](d *schema.ResourceData, setIntegrations func([]sdk.AccountObjectIdentifier) T) error {
integrations, err := parseExternalAccessIntegrationsCommon(d)
if err != nil {
return err
}
setIntegrations(integrations)
return nil
}

func setSecretsInBuilder[T any](d *schema.ResourceData, setSecrets func([]sdk.SecretReference) T) error {
secrets, err := parseSecretsCommon(d)
if err != nil {
return err
}
setSecrets(secrets)
return nil
}

func setFunctionTargetPathInBuilder[T any](d *schema.ResourceData, setTargetPath func(string) T) error {
tp, err := parseFunctionTargetPathCommon(d)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/resources/function_java.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func UpdateContextFunctionJava(ctx context.Context, d *schema.ResourceData, meta
func() error {
if d.HasChange("external_access_integrations") {
return setExternalAccessIntegrationsInBuilder(d, func(references []sdk.AccountObjectIdentifier) any {
if references == nil || len(references) == 0 {
if len(references) == 0 {
return unsetRequest.WithExternalAccessIntegrations(true)
} else {
return setRequest.WithExternalAccessIntegrations(references)
Expand Down
16 changes: 12 additions & 4 deletions pkg/resources/procedure_commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,8 @@ func procedureBaseSchema() map[string]schema.Schema {
ForceNew: true,
},
"comment": {
Type: schema.TypeString,
Optional: true,
// TODO [SNOW-1348103]: handle dynamic comment - this is a workaround for now
Type: schema.TypeString,
Optional: true,
Default: "user-defined procedure",
Description: "Specifies a comment for the procedure.",
},
Expand Down Expand Up @@ -307,7 +306,6 @@ func procedureBaseSchema() map[string]schema.Schema {
ValidateDiagFunc: IsValidIdentifier[sdk.AccountObjectIdentifier](),
},
Optional: true,
ForceNew: true,
Description: "The names of [external access integrations](https://docs.snowflake.com/en/sql-reference/sql/create-external-access-integration) needed in order for this procedure’s handler code to access external networks. An external access integration specifies [network rules](https://docs.snowflake.com/en/sql-reference/sql/create-network-rule) and [secrets](https://docs.snowflake.com/en/sql-reference/sql/create-secret) that specify external locations and credentials (if any) allowed for use by handler code when making requests of an external network, such as an external REST API.",
},
"secrets": {
Expand Down Expand Up @@ -486,6 +484,16 @@ func parseProcedureImportsCommon(d *schema.ResourceData) ([]sdk.ProcedureImportR
return imports, nil
}

func parseProceduresPackagesCommon(d *schema.ResourceData) ([]sdk.ProcedurePackageRequest, error) {
packages := make([]sdk.ProcedurePackageRequest, 0)
if v, ok := d.GetOk("packages"); ok {
for _, pkg := range v.(*schema.Set).List() {
packages = append(packages, *sdk.NewProcedurePackageRequest(pkg.(string)))
}
}
return packages, nil
}

func parseProcedureTargetPathCommon(d *schema.ResourceData) (string, error) {
var tp string
if v, ok := d.GetOk("target_path"); ok {
Expand Down
57 changes: 40 additions & 17 deletions pkg/resources/procedure_java.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ func CreateContextProcedureJava(ctx context.Context, d *schema.ResourceData, met
}
handler := d.Get("handler").(string)
runtimeVersion := d.Get("runtime_version").(string)
// TODO [this PR]: handle real packages
packages := []sdk.ProcedurePackageRequest{*sdk.NewProcedurePackageRequest("com.snowflake:snowpark:1.14.0")}

packages, err := parseProceduresPackagesCommon(d)
if err != nil {
return diag.FromErr(err)
}
packages = append(packages, *sdk.NewProcedurePackageRequest(fmt.Sprintf(`%s%s`, sdk.JavaSnowparkPackageString, d.Get("snowpark_package").(string))))

argumentDataTypes := collections.Map(argumentRequests, func(r sdk.ProcedureArgumentRequest) datatypes.DataType { return r.ArgDataType })
id := sdk.NewSchemaObjectIdentifierWithArgumentsNormalized(database, sc, name, argumentDataTypes...)
Expand All @@ -73,12 +77,10 @@ func CreateContextProcedureJava(ctx context.Context, d *schema.ResourceData, met
errs := errors.Join(
booleanStringAttributeCreateBuilder(d, "is_secure", request.WithSecure),
attributeMappedValueCreateBuilder[string](d, "null_input_behavior", request.WithNullInputBehavior, sdk.ToNullInputBehavior),
// TODO [SNOW-1348103]: handle the rest of the attributes
// comment
stringAttributeCreateBuilder(d, "comment", request.WithComment),
setProcedureImportsInBuilder(d, request.WithImports),
// packages
// external_access_integrations
// secrets
setExternalAccessIntegrationsInBuilder(d, request.WithExternalAccessIntegrations),
setSecretsInBuilder(d, request.WithSecrets),
setProcedureTargetPathInBuilder(d, request.WithTargetPath),
stringAttributeCreateBuilder(d, "procedure_definition", request.WithProcedureDefinitionWrapped),
)
Expand Down Expand Up @@ -122,18 +124,18 @@ func ReadContextProcedureJava(ctx context.Context, d *schema.ResourceData, meta
// TODO [SNOW-1348103]: handle setting state to value from config

errs := errors.Join(
// TODO [SNOW-1348103]: set the rest of the fields
// not reading is_secure on purpose (handled as external change to show output)
readFunctionOrProcedureArguments(d, allProcedureDetails.procedureDetails.NormalizedArguments),
d.Set("return_type", allProcedureDetails.procedureDetails.ReturnDataType.ToSql()),
// not reading null_input_behavior on purpose (handled as external change to show output)
setRequiredFromStringPtr(d, "runtime_version", allProcedureDetails.procedureDetails.RuntimeVersion),
// comment
d.Set("comment", allProcedureDetails.procedure.Description),
readFunctionOrProcedureImports(d, allProcedureDetails.procedureDetails.NormalizedImports),
// packages
d.Set("packages", allProcedureDetails.procedureDetails.NormalizedPackages),
d.Set("snowpark_package", allProcedureDetails.procedureDetails.SnowparkVersion),
setRequiredFromStringPtr(d, "handler", allProcedureDetails.procedureDetails.Handler),
// external_access_integrations
// secrets
readFunctionOrProcedureExternalAccessIntegrations(d, allProcedureDetails.procedureDetails.NormalizedExternalAccessIntegrations),
readFunctionOrProcedureSecrets(d, allProcedureDetails.procedureDetails.NormalizedSecrets),
readFunctionOrProcedureTargetPath(d, allProcedureDetails.procedureDetails.NormalizedTargetPath),
setOptionalFromStringPtr(d, "procedure_definition", allProcedureDetails.procedureDetails.Body),
d.Set("procedure_language", allProcedureDetails.procedureDetails.Language),
Expand Down Expand Up @@ -173,11 +175,32 @@ func UpdateContextProcedureJava(ctx context.Context, d *schema.ResourceData, met
setRequest := sdk.NewProcedureSetRequest()
unsetRequest := sdk.NewProcedureUnsetRequest()

// TODO [SNOW-1348103]: handle all updates
// secure
// external access integration
// secrets
// comment
err = errors.Join(
stringAttributeUpdate(d, "comment", &setRequest.Comment, &unsetRequest.Comment),
func() error {
if d.HasChange("secrets") {
return setSecretsInBuilder(d, func(references []sdk.SecretReference) *sdk.ProcedureSetRequest {
return setRequest.WithSecretsList(sdk.SecretsListRequest{SecretsList: references})
})
}
return nil
}(),
func() error {
if d.HasChange("external_access_integrations") {
return setExternalAccessIntegrationsInBuilder(d, func(references []sdk.AccountObjectIdentifier) any {
if len(references) == 0 {
return unsetRequest.WithExternalAccessIntegrations(true)
} else {
return setRequest.WithExternalAccessIntegrations(references)
}
})
}
return nil
}(),
)
if err != nil {
return diag.FromErr(err)
}

if updateParamDiags := handleProcedureParametersUpdate(d, setRequest, unsetRequest); len(updateParamDiags) > 0 {
return updateParamDiags
Expand Down
Loading

0 comments on commit af4fb22

Please sign in to comment.