Skip to content

Commit 1f59bfd

Browse files
authored
[Internal] Generate Effective Fields (#4057)
This PR introduces changes to the TFSDK generator to support “effective fields” for server-provided values. When fields are marked with the new proto annotation `ServerProposedIfEmpty` (name pending final decision, until then the `computed` annotation is used to indicate these fields, while specific fields are excluded), the generator will create an additional computed field (e.g., `Effective<FieldName>`) and add two sync functions to ensure proper handling of user-provided and server-determined values. ### Generated Struct: ``` type ResourceModel struct { OriginalField types.String `tfsdk:"original_field" tf:"optional"` EffectiveField types.String `tfsdk:"effective_field" tf:"computed"` } ``` ### Sync Functions: ``` func (newState *ResourceModel) SyncEffectiveFieldsDuringCreateOrUpdate(plan ResourceModel) { newState.EffectiveField = newState.OriginalField newState.OriginalField = plan.OriginalField } func (newState *ResourceModel) SyncEffectiveFieldsDuringRead(existingState ResourceModel) { if existingState.EffectiveField.ValueString() == newState.OriginalField.ValueString() { newState.OriginalField = existingState.OriginalField } } ``` ## Changes <!-- Summary of your changes that are easy to understand --> ## Tests <!-- How is this tested? Please see the checklist below and also describe any other relevant tests --> - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --------- Co-authored-by: Omer Lachish <[email protected]>
1 parent ef27ec5 commit 1f59bfd

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

.codegen/model.go.tmpl

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,74 @@ import (
1818
"github.com/databricks/databricks-sdk-go/marshal"
1919
"github.com/hashicorp/terraform-plugin-framework/types"
2020
)
21+
{{- $excluded := dict "ShareInfo" (list "CreatedAt" "CreatedBy" "UpdatedAt" "UpdatedBy")
22+
"SharedDataObject" (list "AddedAt" "AddedBy" "Status") -}}
2123
{{range .Types}}
2224
{{- if or .Fields .IsEmpty}}
2325
{{.Comment "// " 80}}
2426
type {{.PascalName}} struct {
27+
{{- $excluded := getOrDefault $excluded .PascalName (list) -}}
2528
{{- range .Fields}}
2629
{{.Comment " // " 80}}
27-
{{.PascalName}} {{template "type" .Entity}} `{{template "field-tag" . }}`{{end}}
30+
{{- $data := dict "field" . "excluded" $excluded }}
31+
{{template "field" $data}}{{if and .Entity.IsComputed (not (in $excluded .PascalName))}}{{ $data := dict "field" . "excluded" $excluded "effective" true }}{{printf "\n"}}{{template "field" $data}}{{end}}{{end}}
32+
}
33+
34+
func (newState *{{.PascalName}}) SyncEffectiveFieldsDuringCreateOrUpdate(plan {{.PascalName}}) {
35+
{{- range .Fields -}}
36+
{{- if and .Entity.IsComputed (or .Entity.IsString .Entity.IsBool .Entity.IsInt64 .Entity.IsFloat64 .Entity.IsInt .Entity.Enum) -}}
37+
{{- if not (in $excluded .PascalName)}}
38+
newState.Effective{{.PascalName}} = newState.{{.PascalName}}
39+
newState.{{.PascalName}} = plan.{{.PascalName}}
40+
{{- end}}
41+
{{- end}}
42+
{{- end}}
43+
}
44+
45+
func (newState *{{.PascalName}}) SyncEffectiveFieldsDuringRead(existingState {{.PascalName}}) {
46+
{{- range .Fields -}}
47+
{{- if and .Entity.IsComputed (or .Entity.IsString .Entity.IsBool .Entity.IsInt64 .Entity.IsFloat64 .Entity.IsInt .Entity.Enum) -}}
48+
{{- if not (in $excluded .PascalName) -}}
49+
{{- $type := "" -}}
50+
{{- if .Entity.IsString}}{{$type = "String"}}{{end}}
51+
{{- if .Entity.IsBool}}{{$type = "Bool"}}{{end}}
52+
{{- if .Entity.IsInt64}}{{$type = "Int64"}}{{end}}
53+
{{- if .Entity.IsFloat64}}{{$type = "Float64"}}{{end}}
54+
{{- if .Entity.IsInt}}{{$type = "Int64"}}{{end}}
55+
{{- if .Entity.Enum}}{{$type = "String"}}{{end}}
56+
if existingState.Effective{{.PascalName}}.Value{{$type}}() == newState.{{.PascalName}}.Value{{$type}}() {
57+
newState.{{.PascalName}} = existingState.{{.PascalName}}
58+
}
59+
{{- end}}
60+
{{- end}}
61+
{{- end}}
2862
}
2963

3064
{{end}}
3165
{{end}}
3266

67+
{{- define "field" -}}
68+
{{if .effective}}Effective{{end}}{{.field.PascalName}} {{template "type" .field.Entity}} `{{template "field-tag" . }}`
69+
{{- end -}}
70+
3371
{{- define "field-tag" -}}
34-
{{if .IsJson}}tfsdk:"{{if and (ne .Entity.Terraform nil) (ne .Entity.Terraform.Alias "") }}{{.Entity.Terraform.Alias}}{{else}}{{.Name}}{{end}}" tf:"{{- $first := true -}}{{- if not .Required -}}{{- if not $first -}},{{end}}optional{{- $first = false -}}{{- end -}}{{- if .Entity.IsObject -}}{{- if not $first -}},{{end}}object{{- $first = false -}}{{- end -}}"{{else}}tfsdk:"-"{{end -}}
72+
{{- $annotations := "" -}}
73+
{{- if in .excluded .field.PascalName -}}
74+
{{- $annotations = (printf "%scomputed,optional," $annotations) -}}
75+
{{- else if .effective -}}
76+
{{- $annotations = (printf "%scomputed,optional," $annotations) -}}
77+
{{- else -}}
78+
{{- if not .field.Required -}}
79+
{{- $annotations = (printf "%soptional," $annotations) -}}
80+
{{- end -}}
81+
{{- if .field.Entity.IsObject -}}
82+
{{- $annotations = (printf "%sobject," $annotations) -}}
83+
{{- end -}}
84+
{{- end -}}
85+
{{- if gt (len $annotations) 0 -}}
86+
{{- $annotations = (printf "%s" (trimSuffix "," $annotations)) -}}
87+
{{- end -}}
88+
{{if .field.IsJson}}tfsdk:"{{if and (ne .field.Entity.Terraform nil) (ne .field.Entity.Terraform.Alias "") }}{{.field.Entity.Terraform.Alias}}{{else}}{{if .effective}}effective_{{end}}{{.field.Name}}{{end}}" tf:"{{$annotations}}"{{else}}tfsdk:"-"{{end -}}
3589
{{- end -}}
3690

3791
{{- define "type" -}}

0 commit comments

Comments
 (0)