diff --git a/pkg/translate/terraform_provider/funcs.go b/pkg/translate/terraform_provider/funcs.go index 60e7662a..002c329d 100644 --- a/pkg/translate/terraform_provider/funcs.go +++ b/pkg/translate/terraform_provider/funcs.go @@ -201,9 +201,16 @@ const copyToPangoTmpl = ` {{- $diag := .Name.LowerCamelCase | printf "%s_diags" }} var {{ $result }}_entry *{{ $.Spec.PangoType }}{{ .Name.CamelCase }} if o.{{ .Name.CamelCase }} != nil { - var {{ $diag }} diag.Diagnostics - {{ $result }}_entry, {{ $diag }} = o.{{ .Name.CamelCase }}.CopyToPango(ctx, encrypted) - diags.Append({{ $diag }}...) + if *obj != nil && (*obj).{{ .Name.CamelCase }} != nil { + {{ $result }}_entry = (*obj).{{ .Name.CamelCase }} + } else { + {{ $result }}_entry = new({{ $.Spec.PangoType }}{{ .Name.CamelCase }}) + } + + diags.Append(o.{{ .Name.CamelCase }}.CopyToPango(ctx, &{{ $result }}_entry, encrypted)...) + if diags.HasError() { + return diags + } } {{- end }} @@ -221,17 +228,23 @@ const copyToPangoTmpl = ` { d := o.{{ .Name.CamelCase }}.ElementsAs(ctx, &{{ $tfEntries }}, false) diags.Append(d...) + if diags.HasError() { + return diags + } for _, elt := range {{ $tfEntries }} { - entry, d := elt.CopyToPango(ctx, encrypted) - diags.Append(d...) + var entry *{{ $pangoType }} + diags.Append(elt.CopyToPango(ctx, &entry, encrypted)...) + if diags.HasError() { + return diags + } {{ $pangoEntries }} = append({{ $pangoEntries }}, *entry) } } {{- else }} - {{ $pangoEntries }} := make([]{{ .ItemsType }}, 0) - { - d := o.{{ .Name.CamelCase }}.ElementsAs(ctx, &{{ $pangoEntries }}, false) - diags.Append(d...) + {{ $pangoEntries }} := make([]{{ .ItemsType }}, 0) + diags.Append(o.{{ .Name.CamelCase }}.ElementsAs(ctx, &{{ $pangoEntries }}, false)...) + if diags.HasError() { + return diags } {{- end }} {{- end }} @@ -246,7 +259,7 @@ const copyToPangoTmpl = ` {{- range .Specs }} {{- $spec := . }} -func (o *{{ .TerraformType }}{{ .ModelOrObject }}) CopyToPango(ctx context.Context, encrypted *map[string]types.String) (*{{ .PangoReturnType }}, diag.Diagnostics) { +func (o *{{ .TerraformType }}{{ .ModelOrObject }}) CopyToPango(ctx context.Context, obj **{{ .PangoReturnType }}, encrypted *map[string]types.String) diag.Diagnostics { var diags diag.Diagnostics {{- range .Params }} {{- $terraformType := printf "%s%s" $spec.TerraformType .Name.CamelCase }} @@ -272,32 +285,33 @@ func (o *{{ .TerraformType }}{{ .ModelOrObject }}) CopyToPango(ctx context.Conte {{- end }} {{- end }} - result := &{{ .PangoReturnType }}{ + if (*obj) == nil { + *obj = new({{ .PangoReturnType }}) + } {{- if .HasEntryName }} - Name: o.Name.ValueString(), + (*obj).Name = o.Name.ValueString() {{- end }} {{- range .Params }} {{- if eq .Type "" }} - {{ .Name.CamelCase }}: {{ .Name.LowerCamelCase }}_entry, + (*obj).{{ .Name.CamelCase }} = {{ .Name.LowerCamelCase }}_entry {{- else if eq .Type "list" }} - {{ .Name.CamelCase }}: {{ .Name.LowerCamelCase }}_pango_entries, + (*obj).{{ .Name.CamelCase }} = {{ .Name.LowerCamelCase }}_pango_entries {{- else }} - {{ .Name.CamelCase }}: {{ .Name.LowerCamelCase }}_value, + (*obj).{{ .Name.CamelCase }} = {{ .Name.LowerCamelCase }}_value {{- end }} {{- end }} {{- range .OneOf }} {{- if eq .Type "" }} - {{ .Name.CamelCase }}: {{ .Name.LowerCamelCase }}_entry, + (*obj).{{ .Name.CamelCase }} = {{ .Name.LowerCamelCase }}_entry {{- else if eq .Type "list" }} - {{ .Name.CamelCase }}: {{ .Name.LowerCamelCase }}_pango_entries, + (*obj).{{ .Name.CamelCase }} = {{ .Name.LowerCamelCase }}_pango_entries {{- else }} - {{ .Name.CamelCase }}: {{ .Name.LowerCamelCase }}_value, + (*obj).{{ .Name.CamelCase }} = {{ .Name.LowerCamelCase }}_value {{- end }} {{- end }} - } - return result, diags + return diags } {{- end }} ` @@ -408,9 +422,10 @@ var {{ .Name.LowerCamelCase }}_list types.List if obj.{{ .Name.CamelCase }} != nil { {{ $result }}_object = new({{ $.Spec.TerraformType }}{{ .Name.CamelCase }}Object) - var {{ $diag }} diag.Diagnostics - {{ $diag }} = {{ $result }}_object.CopyFromPango(ctx, obj.{{ .Name.CamelCase }}, encrypted) - diags.Append({{ $diag }}...) + diags.Append({{ $result }}_object.CopyFromPango(ctx, obj.{{ .Name.CamelCase }}, encrypted)...) + if diags.HasError() { + return diags + } } {{- end }} {{- end }} @@ -418,13 +433,13 @@ var {{ .Name.LowerCamelCase }}_list types.List {{- define "terraformCreateEntryAssignment" }} {{- range .Params }} {{- if eq .Type "" }} - {{- template "terraformCreateEntryAssignmentForParam" Map "Spec" $ "Parameter" . }} + {{- template "EntryAssignmentForParam" Map "Spec" $ "Parameter" . }} {{- end }} {{- end }} {{- range .OneOf }} {{- if eq .Type "" }} - {{- template "terraformCreateEntryAssignmentForParam" Map "Spec" $ "Parameter" . }} + {{- template "EntryAssignmentForParam" Map "Spec" $ "Parameter" . }} {{- end }} {{- end }} {{- end }} diff --git a/pkg/translate/terraform_provider/template.go b/pkg/translate/terraform_provider/template.go index 96e1345a..7fa1cba0 100644 --- a/pkg/translate/terraform_provider/template.go +++ b/pkg/translate/terraform_provider/template.go @@ -410,10 +410,8 @@ state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false) entries := make([]*{{ $resourceSDKStructName }}, len(elements)) idx := 0 for name, elt := range elements { - var list_diags diag.Diagnostics var entry *{{ .resourceSDKName }}.{{ .EntryOrConfig }} - entry, list_diags = elt.CopyToPango(ctx, {{ $ev }}) - resp.Diagnostics.Append(list_diags...) + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, {{ $ev }})...) if resp.Diagnostics.HasError() { return } @@ -433,8 +431,7 @@ for _, elt := range created { continue } var object {{ $resourceTFStructName }} - copy_diags := object.CopyFromPango(ctx, elt, {{ $ev }}) - resp.Diagnostics.Append(copy_diags...) + resp.Diagnostics.Append(object.CopyFromPango(ctx, elt, {{ $ev }})...) if resp.Diagnostics.HasError() { return } @@ -490,10 +487,8 @@ var elements []{{ $resourceTFStructName }} state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false) entries := make([]*{{ $resourceSDKStructName }}, len(elements)) for idx, elt := range elements { - var list_diags diag.Diagnostics var entry *{{ $resourceSDKStructName }} - entry, list_diags = elt.CopyToPango(ctx, {{ $ev }}) - resp.Diagnostics.Append(list_diags...) + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, {{ $ev }})...) if resp.Diagnostics.HasError() { return } @@ -614,15 +609,13 @@ const resourceCreateFunction = ` // Load the desired config. var obj *{{ .resourceSDKName }}.{{ .EntryOrConfig }} - {{ $ev := "nil" }} {{- if .HasEncryptedResources }} {{ $ev = "&ev" }} ev := make(map[string]types.String) {{- end }} - obj, diags := state.CopyToPango(ctx, {{ $ev }}) - resp.Diagnostics.Append(diags...) - if diags.HasError() { + resp.Diagnostics.Append(state.CopyToPango(ctx, &obj, {{ $ev }})...) + if resp.Diagnostics.HasError() { return } @@ -730,8 +723,8 @@ if resp.Diagnostics.HasError() { entries := make([]*{{ $resourceSDKStructName }}, 0, len(elements)) for name, elt := range elements { - entry, err := elt.CopyToPango(ctx, {{ $ev }}) - resp.Diagnostics.Append(err...) + var entry *{{ $resourceSDKStructName }} + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, {{ $ev }})...) if resp.Diagnostics.HasError() { return } @@ -818,8 +811,8 @@ var elements []{{ $resourceTFStructName }} state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false) entries := make([]*{{ $resourceSDKStructName }}, 0, len(elements)) for _, elt := range elements { - entry, err := elt.CopyToPango(ctx, {{ $ev }}) - resp.Diagnostics.Append(err...) + var entry *{{ $resourceSDKStructName }} + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, {{ $ev }})...) if resp.Diagnostics.HasError() { return } @@ -985,10 +978,8 @@ state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false) stateEntries := make([]*{{ $resourceSDKStructName }}, len(elements)) idx := 0 for name, elt := range elements { - var list_diags diag.Diagnostics var entry *{{ $resourceSDKStructName }} - entry, list_diags = elt.CopyToPango(ctx, nil) - resp.Diagnostics.Append(list_diags...) + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, nil)...) if resp.Diagnostics.HasError() { return } @@ -997,17 +988,27 @@ for name, elt := range elements { idx++ } +existing, err := r.manager.ReadMany(ctx, location, stateEntries) +if err != nil && !sdkerrors.IsObjectNotFound(err) { + resp.Diagnostics.AddError("Error while reading entries from the server", err.Error()) + return +} + +existingEntriesByName := make(map[string]*{{ $resourceSDKStructName }}, len(existing)) +for _, elt := range existing { + existingEntriesByName[elt.Name] = elt +} + plan.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false) planEntries := make([]*{{ $resourceSDKStructName }}, len(elements)) idx = 0 for name, elt := range elements { - var list_diags diag.Diagnostics - var entry *{{ $resourceSDKStructName }} - entry, list_diags = elt.CopyToPango(ctx, nil) - resp.Diagnostics.Append(list_diags...) + entry, _ := existingEntriesByName[name] + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, nil)...) if resp.Diagnostics.HasError() { return } + entry.Name = name planEntries[idx] = entry idx++ @@ -1065,37 +1066,45 @@ var elements []{{ $resourceTFStructName }} state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false) stateEntries := make([]*{{ $resourceSDKStructName }}, len(elements)) for idx, elt := range elements { - var list_diags diag.Diagnostics var entry *{{ $resourceSDKStructName }} - entry, list_diags = elt.CopyToPango(ctx, nil) - resp.Diagnostics.Append(list_diags...) + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, nil)...) if resp.Diagnostics.HasError() { return } stateEntries[idx] = entry } +{{ $exhaustive := "sdkmanager.NonExhaustive" }} +{{- if .Exhaustive }} + {{ $exhaustive = "sdkmanager.Exhaustive" }} +trueValue := true +position := rule.Position{First: &trueValue} +{{- else }} +position := state.Position.CopyToPango() +{{- end }} + +existing, err := r.manager.ReadMany(ctx, location, stateEntries, {{ $exhaustive }}) +if err != nil && !sdkerrors.IsObjectNotFound(err) { + resp.Diagnostics.AddError("Error while reading entries from the server", err.Error()) + return +} + +existingEntriesByName := make(map[string]*{{ $resourceSDKStructName }}, len(existing)) +for _, elt := range existing { + existingEntriesByName[elt.Name] = elt +} + plan.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false) planEntries := make([]*{{ $resourceSDKStructName }}, len(elements)) for idx, elt := range elements { - var list_diags diag.Diagnostics - var entry *{{ $resourceSDKStructName }} - entry, list_diags = elt.CopyToPango(ctx, nil) - resp.Diagnostics.Append(list_diags...) + entry, _ := existingEntriesByName[elt.Name.ValueString()] + resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, nil)...) if resp.Diagnostics.HasError() { return } planEntries[idx] = entry } -{{ $exhaustive := "sdkmanager.NonExhaustive" }} -{{- if .Exhaustive }} - {{ $exhaustive = "sdkmanager.Exhaustive" }} -trueValue := true -position := rule.Position{First: &trueValue} -{{- else }} -position := state.Position.CopyToPango() -{{- end }} processed, err := r.manager.UpdateMany(ctx, location, stateEntries, planEntries, {{ $exhaustive }}, position) if err != nil { resp.Diagnostics.AddError("Failed to udpate entries", err.Error()) @@ -1123,6 +1132,8 @@ resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) ` const resourceUpdateFunction = ` +{{ $resourceSDKStructName := printf "%s.%s" .resourceSDKName .EntryOrConfig }} + var plan, state {{ .structName }}Model resp.Diagnostics.Append(req.State.Get(ctx, &state)...) resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) @@ -1159,10 +1170,17 @@ const resourceUpdateFunction = ` return } - // Create the service. +{{- if .HasEntryName }} + obj, err := r.manager.Read(ctx, loc.Location, loc.Name) +{{- else }} + obj, err := r.manager.Read(ctx, loc.Location) +{{- end }} + if err != nil { + resp.Diagnostics.AddError("Error in update", err.Error()) + return + } - obj, copy_diags := plan.CopyToPango(ctx, {{ $ev }}) - resp.Diagnostics.Append(copy_diags...) + resp.Diagnostics.Append(plan.CopyToPango(ctx, &obj, {{ $ev }})...) if resp.Diagnostics.HasError() { return } @@ -1197,7 +1215,7 @@ const resourceUpdateFunction = ` } state.Tfid = types.StringValue(tfid) - copy_diags = state.CopyFromPango(ctx, updated, {{ $ev }}) + copy_diags := state.CopyFromPango(ctx, updated, {{ $ev }}) {{- if .HasEncryptedResources }} ev_map, ev_diags := types.MapValueFrom(ctx, types.StringType, ev) state.EncryptedValues = ev_map @@ -1264,6 +1282,8 @@ if err != nil { ` const resourceDeleteFunction = ` +{{ $resourceSDKStructName := printf "%s.%s" .resourceSDKName .EntryOrConfig }} + var state {{ .structName }}Model resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { @@ -1304,14 +1324,14 @@ const resourceDeleteFunction = ` } {{- else }} +{{- $ev := "nil" }} {{- if .HasEncryptedResources }} + {{- $ev = "&ev" }} ev := make(map[string]types.String) - obj, diags := state.CopyToPango(ctx, &ev) -{{- else }} - obj, diags := state.CopyToPango(ctx, nil) {{- end }} - resp.Diagnostics.Append(diags...) - if diags.HasError() { + var obj *{{ $resourceSDKStructName }} + resp.Diagnostics.Append(state.CopyToPango(ctx, &obj, {{ $ev }})...) + if resp.Diagnostics.HasError() { return } diff --git a/pkg/translate/terraform_provider/terraform_provider_file.go b/pkg/translate/terraform_provider/terraform_provider_file.go index d1ea154b..26dbe282 100644 --- a/pkg/translate/terraform_provider/terraform_provider_file.go +++ b/pkg/translate/terraform_provider/terraform_provider_file.go @@ -188,9 +188,13 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper switch resourceTyp { case properties.ResourceUuid: terraformProvider.ImportManager.AddSdkImport("github.com/PaloAltoNetworks/pango/rule", "") + terraformProvider.ImportManager.AddSdkImport("github.com/PaloAltoNetworks/pango/errors", "sdkerrors") case properties.ResourceEntry: case properties.ResourceUuidPlural: - case properties.ResourceEntryPlural, properties.ResourceCustom: + terraformProvider.ImportManager.AddSdkImport("github.com/PaloAltoNetworks/pango/errors", "sdkerrors") + case properties.ResourceEntryPlural: + terraformProvider.ImportManager.AddSdkImport("github.com/PaloAltoNetworks/pango/errors", "sdkerrors") + case properties.ResourceCustom: } // Generate Resource with entry style