From 2155e70b6bc83489b65f788e228307219ce1edb6 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Mon, 4 Mar 2024 16:19:26 +0100 Subject: [PATCH 01/19] new function to make indentation equal in list of strings --- pkg/translate/names.go | 21 ++++++++++++++++++++- pkg/translate/names_test.go | 12 ++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/pkg/translate/names.go b/pkg/translate/names.go index d584fce1..bd9133ee 100644 --- a/pkg/translate/names.go +++ b/pkg/translate/names.go @@ -1,9 +1,28 @@ package translate -// Get package name from Go SDK path +import "strings" + +// PackageName Get package name from Go SDK path func PackageName(list []string) string { if len(list) == 0 { return "" } return list[len(list)-1] } + +// MakeIndentationEqual Check max lenght of the string in the list and then add spaces at the end of very name to make equal indentation +func MakeIndentationEqual(list []string) []string { + maxLength := 0 + + for _, str := range list { + if len(str) > maxLength { + maxLength = len(str) + } + } + + for idx, str := range list { + list[idx] = str + strings.Repeat(" ", maxLength-len(str)) + } + + return list +} diff --git a/pkg/translate/names_test.go b/pkg/translate/names_test.go index f0a7c2cc..8f3a6738 100644 --- a/pkg/translate/names_test.go +++ b/pkg/translate/names_test.go @@ -15,3 +15,15 @@ func TestPackageName(t *testing.T) { // then assert.Equal(t, "address", packageName) } + +func TestMakeIndentationEqual(t *testing.T) { + // given + givenItems := []string{"test", "a"} + exptectedItems := []string{"test", "a "} + + // when + changedItems := MakeIndentationEqual(givenItems) + + // then + assert.Equal(t, exptectedItems, changedItems) +} From d5ffed6cac71767eedaa0458c222cace4adcda1e Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Mon, 4 Mar 2024 16:19:41 +0100 Subject: [PATCH 02/19] execute new function creating definition of structs --- pkg/generate/generator.go | 3 ++- templates/sdk/location.tmpl | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go index fa67a141..7d35bf47 100644 --- a/pkg/generate/generator.go +++ b/pkg/generate/generator.go @@ -75,7 +75,8 @@ func (c *Creator) generateOutputFileFromTemplate(tmpl *template.Template, output func (c *Creator) parseTemplate(templateName string) (*template.Template, error) { templatePath := fmt.Sprintf("%s/%s", c.TemplatesDir, templateName) funcMap := template.FuncMap{ - "packageName": translate.PackageName, + "packageName": translate.PackageName, + "structsDefinitionsForLocation": translate.StructsDefinitionsForLocation, } tmpl, err := template.New(templateName).Funcs(funcMap).ParseFiles(templatePath) if err != nil { diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index 0c27f6b2..510ac88b 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -7,3 +7,5 @@ import ( "github.com/PaloAltoNetworks/pango/util" "github.com/PaloAltoNetworks/pango/version" ) + +{{ structsDefinitionsForLocation .Locations }} \ No newline at end of file From dcb8f2eab2c1fc6257fd9183f2e6102b4aa2288a Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Mon, 4 Mar 2024 16:20:00 +0100 Subject: [PATCH 03/19] new function creating definition of structs (with tests) --- pkg/translate/structs.go | 55 +++++++++++++ pkg/translate/structs_test.go | 149 ++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 pkg/translate/structs.go create mode 100644 pkg/translate/structs_test.go diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go new file mode 100644 index 00000000..405f8c91 --- /dev/null +++ b/pkg/translate/structs.go @@ -0,0 +1,55 @@ +package translate + +import ( + "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" + "strings" +) + +func StructsDefinitionsForLocation(locations map[string]*properties.Location) (string, error) { + var builder strings.Builder + + builder.WriteString("type Location struct {\n") + for name := range locations { + switch name { + case "shared": + builder.WriteString("\tShared bool `json:\"shared\"`\n") + case "from_panorama": + builder.WriteString("\tFromPanorama bool `json:\"from_panorama\"`\n") + case "vsys": + builder.WriteString("\tVsys *VsysLocation `json:\"vsys,omitempty\"`\n") + case "device_group": + builder.WriteString("\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n") + } + } + builder.WriteString("}\n\n") + + if _, ok := locations["vsys"]; ok { + var vars []string + for name := range locations["vsys"].Vars { + vars = append(vars, name) + } + vars = MakeIndentationEqual(vars) + + builder.WriteString("type VsysLocation struct {\n") + for _, name := range vars { + builder.WriteString("\t" + name + "\tstring `json:\"" + name + "\"`\n") + } + builder.WriteString("}\n\n") + } + + if _, ok := locations["device_group"]; ok { + var vars []string + for name := range locations["device_group"].Vars { + vars = append(vars, name) + } + vars = MakeIndentationEqual(vars) + + builder.WriteString("type DeviceGroupLocation struct {\n") + for _, name := range vars { + builder.WriteString("\t" + name + "\tstring `json:\"" + strings.TrimSpace(name) + "\"`\n") + } + builder.WriteString("}\n\n") + } + + return builder.String(), nil +} diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go new file mode 100644 index 00000000..0fb8e731 --- /dev/null +++ b/pkg/translate/structs_test.go @@ -0,0 +1,149 @@ +package translate + +import ( + "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestStructsDefinitionsForLocation(t *testing.T) { + // given + var sampleSpec = `name: 'Address' +terraform_provider_suffix: 'address' +go_sdk_path: + - 'objects' + - 'address' +xpath_suffix: + - 'address' +locations: + 'shared': + description: 'Located in shared.' + device: + panorama: true + ngfw: true + xpath: ['config', 'shared'] + 'from_panorama': + description: 'Located in the config pushed from Panorama.' + read_only: true + device: + ngfw: true + xpath: ['config', 'panorama'] + 'vsys': + description: 'Located in a specific vsys.' + device: + panorama: true + ngfw: true + xpath: + - 'config' + - 'devices' + - '{{ Entry $ngfw_device }}' + - 'vsys' + - '{{ Entry $vsys }}' + vars: + 'ngfw_device': + description: 'The NGFW device.' + default: 'localhost.localdomain' + 'vsys': + description: 'The vsys.' + default: 'vsys1' + validation: + not_values: + 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' + 'device_group': + description: 'Located in a specific device group.' + device: + panorama: true + xpath: + - 'config' + - 'devices' + - '{{ Entry $panorama_device }}' + - 'device-group' + - '{{ Entry $device_group }}' + vars: + 'panorama_device': + description: 'The panorama device.' + default: 'localhost.localdomain' + 'device_group': + description: 'The device group.' + required: true + validation: + not_values: + 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' +entry: + name: + description: 'The name of the address object.' + length: + min: 1 + max: 63 +version: '10.1.0' +spec: + params: + description: + description: 'The description.' + type: 'string' + length: + min: 0 + max: 1023 + profiles: + - + xpath: ["description"] + tags: + description: 'The administrative tags.' + type: 'list' + count: + max: 64 + items: + type: 'string' + length: + max: 127 + profiles: + - + type: 'member' + xpath: ["tag"] + one_of: + 'ip_netmask': + description: 'The IP netmask value.' + profiles: + - + xpath: ["ip-netmask"] + 'ip_range': + description: 'The IP range value.' + profiles: + - + xpath: ["ip-range"] + 'fqdn': + description: 'The FQDN value.' + regex: '^[a-zA-Z0-9_]([a-zA-Z0-9:_-])+[a-zA-Z0-9]$' + length: + min: 1 + max: 255 + profiles: + - + xpath: ["fqdn"] + 'ip_wildcard': + description: 'The IP wildcard value.' + profiles: + - + xpath: ["ip-wildcard"] +` + var expectedStructsForLocation = "type Location struct {\n" + + "\tShared bool `json:\"shared\"`\n" + + "\tFromPanorama bool `json:\"from_panorama\"`\n" + + "\tVsys *VsysLocation `json:\"vsys,omitempty\"`\n" + + "\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n" + + "}\n" + + "\ntype VsysLocation struct {\n" + + "\tngfw_device\tstring `json:\"ngfw_device\"`\n" + + "\tvsys \tstring `json:\"vsys \"`\n}\n" + + "\ntype DeviceGroupLocation struct {\n" + + "\tpanorama_device\tstring `json:\"panorama_device\"`\n" + + "\tdevice_group \tstring `json:\"device_group\"`\n" + + "}\n\n" + + // when + yamlParsedData, _ := properties.ParseSpec([]byte(sampleSpec)) + structsForLocation, _ := StructsDefinitionsForLocation(yamlParsedData.Locations) + + // then + assert.Equal(t, expectedStructsForLocation, structsForLocation) +} From 7c5f19ba633f6c8a6fb1ab482da34c2951692aca Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Mon, 4 Mar 2024 16:31:41 +0100 Subject: [PATCH 04/19] fix logic after tests --- pkg/translate/structs.go | 23 +++++++++++++---------- pkg/translate/structs_test.go | 8 ++++---- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index 405f8c91..175f87ad 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -1,6 +1,7 @@ package translate import ( + "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" "strings" ) @@ -24,29 +25,31 @@ func StructsDefinitionsForLocation(locations map[string]*properties.Location) (s builder.WriteString("}\n\n") if _, ok := locations["vsys"]; ok { - var vars []string + var namesOriginal, namesCamelCaseWithSpaces []string for name := range locations["vsys"].Vars { - vars = append(vars, name) + namesOriginal = append(namesOriginal, name) + namesCamelCaseWithSpaces = append(namesCamelCaseWithSpaces, naming.CamelCase("", name, "", true)) } - vars = MakeIndentationEqual(vars) + namesCamelCaseWithSpaces = MakeIndentationEqual(namesCamelCaseWithSpaces) builder.WriteString("type VsysLocation struct {\n") - for _, name := range vars { - builder.WriteString("\t" + name + "\tstring `json:\"" + name + "\"`\n") + for idx, name := range namesCamelCaseWithSpaces { + builder.WriteString("\t" + name + " string `json:\"" + namesOriginal[idx] + "\"`\n") } builder.WriteString("}\n\n") } if _, ok := locations["device_group"]; ok { - var vars []string + var namesOriginal, namesCamelCaseWithSpaces []string for name := range locations["device_group"].Vars { - vars = append(vars, name) + namesOriginal = append(namesOriginal, name) + namesCamelCaseWithSpaces = append(namesCamelCaseWithSpaces, naming.CamelCase("", name, "", true)) } - vars = MakeIndentationEqual(vars) + namesCamelCaseWithSpaces = MakeIndentationEqual(namesCamelCaseWithSpaces) builder.WriteString("type DeviceGroupLocation struct {\n") - for _, name := range vars { - builder.WriteString("\t" + name + "\tstring `json:\"" + strings.TrimSpace(name) + "\"`\n") + for idx, name := range namesCamelCaseWithSpaces { + builder.WriteString("\t" + name + " string `json:\"" + namesOriginal[idx] + "\"`\n") } builder.WriteString("}\n\n") } diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go index 0fb8e731..bf7bbe40 100644 --- a/pkg/translate/structs_test.go +++ b/pkg/translate/structs_test.go @@ -133,11 +133,11 @@ spec: "\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n" + "}\n" + "\ntype VsysLocation struct {\n" + - "\tngfw_device\tstring `json:\"ngfw_device\"`\n" + - "\tvsys \tstring `json:\"vsys \"`\n}\n" + + "\tNgfwDevice string `json:\"ngfw_device\"`\n" + + "\tVsys string `json:\"vsys\"`\n}\n" + "\ntype DeviceGroupLocation struct {\n" + - "\tpanorama_device\tstring `json:\"panorama_device\"`\n" + - "\tdevice_group \tstring `json:\"device_group\"`\n" + + "\tPanoramaDevice string `json:\"panorama_device\"`\n" + + "\tDeviceGroup string `json:\"device_group\"`\n" + "}\n\n" // when From 81718270936bcb578ac9be8fd2292ead093e7288 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Mon, 4 Mar 2024 16:38:57 +0100 Subject: [PATCH 05/19] refactor code (remove duplication and extract func) --- pkg/translate/structs.go | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index 175f87ad..7684f2a4 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -24,35 +24,25 @@ func StructsDefinitionsForLocation(locations map[string]*properties.Location) (s } builder.WriteString("}\n\n") - if _, ok := locations["vsys"]; ok { - var namesOriginal, namesCamelCaseWithSpaces []string - for name := range locations["vsys"].Vars { - namesOriginal = append(namesOriginal, name) - namesCamelCaseWithSpaces = append(namesCamelCaseWithSpaces, naming.CamelCase("", name, "", true)) - } - namesCamelCaseWithSpaces = MakeIndentationEqual(namesCamelCaseWithSpaces) + nestedStructsDefinitionsForLocation(locations, "vsys", "VsysLocation", &builder) + nestedStructsDefinitionsForLocation(locations, "device_group", "DeviceGroupLocation", &builder) - builder.WriteString("type VsysLocation struct {\n") - for idx, name := range namesCamelCaseWithSpaces { - builder.WriteString("\t" + name + " string `json:\"" + namesOriginal[idx] + "\"`\n") - } - builder.WriteString("}\n\n") - } + return builder.String(), nil +} - if _, ok := locations["device_group"]; ok { +func nestedStructsDefinitionsForLocation(locations map[string]*properties.Location, locationName string, structName string, builder *strings.Builder) { + if _, ok := locations[locationName]; ok { var namesOriginal, namesCamelCaseWithSpaces []string - for name := range locations["device_group"].Vars { + for name := range locations[locationName].Vars { namesOriginal = append(namesOriginal, name) namesCamelCaseWithSpaces = append(namesCamelCaseWithSpaces, naming.CamelCase("", name, "", true)) } namesCamelCaseWithSpaces = MakeIndentationEqual(namesCamelCaseWithSpaces) - builder.WriteString("type DeviceGroupLocation struct {\n") + builder.WriteString("type " + structName + " struct {\n") for idx, name := range namesCamelCaseWithSpaces { builder.WriteString("\t" + name + " string `json:\"" + namesOriginal[idx] + "\"`\n") } builder.WriteString("}\n\n") } - - return builder.String(), nil } From 7aad15572668ba59b56183c944b794947d9eaf7e Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 09:05:29 +0100 Subject: [PATCH 06/19] fix random order in keys for maps --- pkg/translate/structs.go | 18 +++++++++++++++--- pkg/translate/structs_test.go | 6 +++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index 7684f2a4..5e686be8 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -3,14 +3,20 @@ package translate import ( "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" + "sort" "strings" ) func StructsDefinitionsForLocation(locations map[string]*properties.Location) (string, error) { - var builder strings.Builder + keys := make([]string, 0, len(locations)) + for key := range locations { + keys = append(keys, key) + } + sort.Strings(keys) + var builder strings.Builder builder.WriteString("type Location struct {\n") - for name := range locations { + for _, name := range keys { switch name { case "shared": builder.WriteString("\tShared bool `json:\"shared\"`\n") @@ -32,8 +38,14 @@ func StructsDefinitionsForLocation(locations map[string]*properties.Location) (s func nestedStructsDefinitionsForLocation(locations map[string]*properties.Location, locationName string, structName string, builder *strings.Builder) { if _, ok := locations[locationName]; ok { + keys := make([]string, 0, len(locations[locationName].Vars)) + for key := range locations[locationName].Vars { + keys = append(keys, key) + } + sort.Strings(keys) + var namesOriginal, namesCamelCaseWithSpaces []string - for name := range locations[locationName].Vars { + for _, name := range keys { namesOriginal = append(namesOriginal, name) namesCamelCaseWithSpaces = append(namesCamelCaseWithSpaces, naming.CamelCase("", name, "", true)) } diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go index bf7bbe40..4a4b38bd 100644 --- a/pkg/translate/structs_test.go +++ b/pkg/translate/structs_test.go @@ -127,17 +127,17 @@ spec: xpath: ["ip-wildcard"] ` var expectedStructsForLocation = "type Location struct {\n" + - "\tShared bool `json:\"shared\"`\n" + + "\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n" + "\tFromPanorama bool `json:\"from_panorama\"`\n" + + "\tShared bool `json:\"shared\"`\n" + "\tVsys *VsysLocation `json:\"vsys,omitempty\"`\n" + - "\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n" + "}\n" + "\ntype VsysLocation struct {\n" + "\tNgfwDevice string `json:\"ngfw_device\"`\n" + "\tVsys string `json:\"vsys\"`\n}\n" + "\ntype DeviceGroupLocation struct {\n" + - "\tPanoramaDevice string `json:\"panorama_device\"`\n" + "\tDeviceGroup string `json:\"device_group\"`\n" + + "\tPanoramaDevice string `json:\"panorama_device\"`\n" + "}\n\n" // when From b2bef135d6320b85c13b14eb3bf1e2a7d21d8a51 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 09:14:39 +0100 Subject: [PATCH 07/19] update testify package --- go.mod | 2 +- go.sum | 4 ++-- pkg/translate/names_test.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index f5ca045f..254507b4 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/paloaltonetworks/pan-os-codegen require ( - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index fa4b6e68..60ce688a 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/translate/names_test.go b/pkg/translate/names_test.go index 8f3a6738..0b4e5d6a 100644 --- a/pkg/translate/names_test.go +++ b/pkg/translate/names_test.go @@ -19,11 +19,11 @@ func TestPackageName(t *testing.T) { func TestMakeIndentationEqual(t *testing.T) { // given givenItems := []string{"test", "a"} - exptectedItems := []string{"test", "a "} + expectedItems := []string{"test", "a "} // when changedItems := MakeIndentationEqual(givenItems) // then - assert.Equal(t, exptectedItems, changedItems) + assert.Equal(t, expectedItems, changedItems) } From cd267f23fdf268eedd255e93c6c72460ac561ca7 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 10:40:20 +0100 Subject: [PATCH 08/19] new functions to generate functions for locations --- pkg/translate/funcs.go | 150 ++++++++++++++++++++++++++++++++++++ pkg/translate/funcs_test.go | 1 + 2 files changed, 151 insertions(+) create mode 100644 pkg/translate/funcs.go create mode 100644 pkg/translate/funcs_test.go diff --git a/pkg/translate/funcs.go b/pkg/translate/funcs.go new file mode 100644 index 00000000..10a87a5b --- /dev/null +++ b/pkg/translate/funcs.go @@ -0,0 +1,150 @@ +package translate + +import ( + "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" + "sort" + "strings" +) + +func FuncBodyForLocation(locations map[string]*properties.Location) (string, error) { + keys := make([]string, 0, len(locations)) + for key := range locations { + keys = append(keys, key) + } + sort.Strings(keys) + + mapIsValid := map[string]string{ + "shared": ` + case o.Shared: + count++ +`, + + "from_panorama": ` + case o.FromPanorama: + count++ +`, + + "vsys": ` + case o.Vsys != nil: + if o.Vsys.Vsys == "" { + return fmt.Errorf("vsys.vsys is unspecified") + } + if o.Vsys.NgfwDevice == "" { + return fmt.Errorf("vsys.ngfw_device is unspecified") + } + count++ +`, + + "device_group": ` + case o.DeviceGroup != nil: + if o.DeviceGroup.DeviceGroup == "" { + return fmt.Errorf("device_group.device_group is unspecified") + } + if o.DeviceGroup.PanoramaDevice == "" { + return fmt.Errorf("device_group.panorama_device is unspecified") + } + count++ +`, + } + mapXpath := map[string]string{ + "shared": ` + case o.Shared: + ans = []string{ + "config", + "shared", + } +`, + + "from_panorama": ` + case o.FromPanorama: + ans = []string{"config", "panorama"} +`, + + "vsys": ` + case o.Vsys != nil: + if o.Vsys.NgfwDevice == "" { + return nil, fmt.Errorf("NgfwDevice is unspecified") + } + if o.Vsys.Vsys == "" { + return nil, fmt.Errorf("Vsys is unspecified") + } + ans = []string{ + "config", + "devices", + util.AsEntryXpath([]string{o.Vsys.NgfwDevice}), + "vsys", + util.AsEntryXpath([]string{o.Vsys.Vsys}), + } +`, + + "device_group": ` + case o.DeviceGroup != nil: + if o.DeviceGroup.PanoramaDevice == "" { + return nil, fmt.Errorf("PanoramaDevice is unspecified") + } + if o.DeviceGroup.DeviceGroup == "" { + return nil, fmt.Errorf("DeviceGroup is unspecified") + } + ans = []string{ + "config", + "devices", + util.AsEntryXpath([]string{o.DeviceGroup.PanoramaDevice}), + "device-group", + util.AsEntryXpath([]string{o.DeviceGroup.DeviceGroup}), + } +`, + } + + var builder strings.Builder + funcBodyForLocation(&builder, keys, "IsValid", "()", "error", false, + ` count := 0 + + switch { +`, + ` } + + if count == 0 { + return fmt.Errorf("no path specified") + } + + if count > 1 { + return fmt.Errorf("multiple paths specified: only one should be specified") + } + + return nil +`, + mapIsValid) + funcBodyForLocation(&builder, keys, "Xpath", "(vn version.Number, name string)", "([]string, error)", + true, ` + var ans []string + + switch { +`, + ` + default: + return nil, errors.NoLocationSpecifiedError + } + + ans = append(ans, Suffix...) + ans = append(ans, util.AsEntryXpath([]string{name})) + + return ans, nil +`, + mapXpath) + + return builder.String(), nil +} + +func funcBodyForLocation(builder *strings.Builder, keys []string, funcName string, funcInput string, funcOutput string, + startFromNewLine bool, funcBegin string, funcEnd string, funcCases map[string]string) { + if startFromNewLine { + builder.WriteString("\n") + } + builder.WriteString("func (o Location) " + funcName + funcInput + " " + funcOutput + " {\n") + builder.WriteString(funcBegin) + for _, name := range keys { + builder.WriteString(funcCases[name]) + } + builder.WriteString(funcEnd) + builder.WriteString("}\n") +} diff --git a/pkg/translate/funcs_test.go b/pkg/translate/funcs_test.go new file mode 100644 index 00000000..c2cb5d52 --- /dev/null +++ b/pkg/translate/funcs_test.go @@ -0,0 +1 @@ +package translate From e975329f07d336c29e1a928d183a3cbf03ec291a Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 10:40:37 +0100 Subject: [PATCH 09/19] use new functions for locations --- pkg/generate/generator.go | 1 + pkg/translate/structs.go | 8 ++++---- pkg/translate/structs_test.go | 10 +++++----- templates/sdk/location.tmpl | 3 ++- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go index 7d35bf47..8dcc5d33 100644 --- a/pkg/generate/generator.go +++ b/pkg/generate/generator.go @@ -77,6 +77,7 @@ func (c *Creator) parseTemplate(templateName string) (*template.Template, error) funcMap := template.FuncMap{ "packageName": translate.PackageName, "structsDefinitionsForLocation": translate.StructsDefinitionsForLocation, + "funcBodyForLocation": translate.FuncBodyForLocation, } tmpl, err := template.New(templateName).Funcs(funcMap).ParseFiles(templatePath) if err != nil { diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index 5e686be8..fb96eb85 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -28,7 +28,7 @@ func StructsDefinitionsForLocation(locations map[string]*properties.Location) (s builder.WriteString("\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n") } } - builder.WriteString("}\n\n") + builder.WriteString("}\n") nestedStructsDefinitionsForLocation(locations, "vsys", "VsysLocation", &builder) nestedStructsDefinitionsForLocation(locations, "device_group", "DeviceGroupLocation", &builder) @@ -51,10 +51,10 @@ func nestedStructsDefinitionsForLocation(locations map[string]*properties.Locati } namesCamelCaseWithSpaces = MakeIndentationEqual(namesCamelCaseWithSpaces) - builder.WriteString("type " + structName + " struct {\n") + builder.WriteString("\ntype " + structName + " struct {\n") for idx, name := range namesCamelCaseWithSpaces { - builder.WriteString("\t" + name + " string `json:\"" + namesOriginal[idx] + "\"`\n") + builder.WriteString("\t" + name + " string `json:\"" + namesOriginal[idx] + "\"`\n") } - builder.WriteString("}\n\n") + builder.WriteString("}\n") } } diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go index 4a4b38bd..6a2f4071 100644 --- a/pkg/translate/structs_test.go +++ b/pkg/translate/structs_test.go @@ -133,12 +133,12 @@ spec: "\tVsys *VsysLocation `json:\"vsys,omitempty\"`\n" + "}\n" + "\ntype VsysLocation struct {\n" + - "\tNgfwDevice string `json:\"ngfw_device\"`\n" + - "\tVsys string `json:\"vsys\"`\n}\n" + + "\tNgfwDevice string `json:\"ngfw_device\"`\n" + + "\tVsys string `json:\"vsys\"`\n}\n" + "\ntype DeviceGroupLocation struct {\n" + - "\tDeviceGroup string `json:\"device_group\"`\n" + - "\tPanoramaDevice string `json:\"panorama_device\"`\n" + - "}\n\n" + "\tDeviceGroup string `json:\"device_group\"`\n" + + "\tPanoramaDevice string `json:\"panorama_device\"`\n" + + "}\n" // when yamlParsedData, _ := properties.ParseSpec([]byte(sampleSpec)) diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index 510ac88b..f7e6a381 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -8,4 +8,5 @@ import ( "github.com/PaloAltoNetworks/pango/version" ) -{{ structsDefinitionsForLocation .Locations }} \ No newline at end of file +{{ structsDefinitionsForLocation .Locations }} +{{ funcBodyForLocation .Locations }} \ No newline at end of file From b5095ac82fd160633c2ed6c1bd1bc10acce7fa0f Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 11:54:20 +0100 Subject: [PATCH 10/19] extend template, do not concat strings to generate structs --- pkg/generate/generator.go | 4 ++++ pkg/translate/structs.go | 20 ++++++++++++++++++++ templates/sdk/location.tmpl | 18 ++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go index 8dcc5d33..cc039df0 100644 --- a/pkg/generate/generator.go +++ b/pkg/generate/generator.go @@ -2,6 +2,7 @@ package generate import ( "fmt" + "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" "github.com/paloaltonetworks/pan-os-codegen/pkg/translate" "io" @@ -78,6 +79,9 @@ func (c *Creator) parseTemplate(templateName string) (*template.Template, error) "packageName": translate.PackageName, "structsDefinitionsForLocation": translate.StructsDefinitionsForLocation, "funcBodyForLocation": translate.FuncBodyForLocation, + "camelCase": naming.CamelCase, + "locationType": translate.LocationType, + "omitEmpty": translate.OmitEmpty, } tmpl, err := template.New(templateName).Funcs(funcMap).ParseFiles(templatePath) if err != nil { diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index fb96eb85..35d6e02e 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -7,6 +7,26 @@ import ( "strings" ) +func LocationType(name string, location properties.Location, pointer bool) string { + prefix := "" + if pointer { + prefix = "*" + } + if location.Vars != nil { + return prefix + naming.CamelCase("", name, "", true) + "Location" + } else { + return "bool" + } +} + +func OmitEmpty(location properties.Location) string { + if location.Vars != nil { + return ",omitempty" + } else { + return "" + } +} + func StructsDefinitionsForLocation(locations map[string]*properties.Location) (string, error) { keys := make([]string, 0, len(locations)) for key := range locations { diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index f7e6a381..b6024a81 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -1,4 +1,4 @@ -package {{ packageName .GoSdkPath }} +package {{packageName .GoSdkPath }} import ( "fmt" @@ -8,5 +8,19 @@ import ( "github.com/PaloAltoNetworks/pango/version" ) -{{ structsDefinitionsForLocation .Locations }} +type Location struct { + {{range $key, $location := .Locations}} + {{- camelCase "" $key "" true}} {{locationType $key $location true}} `json:"{{$key}}{{omitEmpty $location}}"` + {{end}} +} +{{range $key, $location := .Locations}} +{{- if $location.Vars}} +type {{locationType $key $location false}} struct { +{{- range $key, $var := $location.Vars}} + {{camelCase "" $key "" true}} string `json:"{{$key}}"` +{{- end}} +} +{{- end}} +{{- end}} + {{ funcBodyForLocation .Locations }} \ No newline at end of file From a07ae67955b19770dfdc169735b2cacce6f5677f Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 12:58:39 +0100 Subject: [PATCH 11/19] extend template, do not concat strings to generate functions --- pkg/generate/generator.go | 12 +++++-- pkg/translate/funcs.go | 8 +++++ templates/sdk/location.tmpl | 62 +++++++++++++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go index cc039df0..8770dfb8 100644 --- a/pkg/generate/generator.go +++ b/pkg/generate/generator.go @@ -79,9 +79,15 @@ func (c *Creator) parseTemplate(templateName string) (*template.Template, error) "packageName": translate.PackageName, "structsDefinitionsForLocation": translate.StructsDefinitionsForLocation, "funcBodyForLocation": translate.FuncBodyForLocation, - "camelCase": naming.CamelCase, - "locationType": translate.LocationType, - "omitEmpty": translate.OmitEmpty, + "camelCase": func(name string) string { + return naming.CamelCase("", name, "", true) + }, + "locationType": translate.LocationType, + "omitEmpty": translate.OmitEmpty, + "contains": func(full, part string) bool { + return strings.Contains(full, part) + }, + "asEntryXpath": translate.AsEntryXpath, } tmpl, err := template.New(templateName).Funcs(funcMap).ParseFiles(templatePath) if err != nil { diff --git a/pkg/translate/funcs.go b/pkg/translate/funcs.go index 10a87a5b..36a3212f 100644 --- a/pkg/translate/funcs.go +++ b/pkg/translate/funcs.go @@ -1,11 +1,19 @@ package translate import ( + "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" "sort" "strings" ) +func AsEntryXpath(location, xpath string) string { + location = naming.CamelCase("", location, "", true) + xpath = strings.TrimSpace(strings.Split(strings.Split(xpath, "$")[1], "}")[0]) + xpath = naming.CamelCase("", xpath, "", true) + return "util.AsEntryXpath([]string{o." + location + "." + xpath + "})," +} + func FuncBodyForLocation(locations map[string]*properties.Location) (string, error) { keys := make([]string, 0, len(locations)) for key := range locations { diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index b6024a81..b229a1c2 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -10,17 +10,73 @@ import ( type Location struct { {{range $key, $location := .Locations}} - {{- camelCase "" $key "" true}} {{locationType $key $location true}} `json:"{{$key}}{{omitEmpty $location}}"` + {{- camelCase $key}} {{locationType $key $location true}} `json:"{{$key}}{{omitEmpty $location}}"` {{end}} } {{range $key, $location := .Locations}} {{- if $location.Vars}} type {{locationType $key $location false}} struct { {{- range $key, $var := $location.Vars}} - {{camelCase "" $key "" true}} string `json:"{{$key}}"` + {{camelCase $key}} string `json:"{{$key}}"` {{- end}} } {{- end}} {{- end}} -{{ funcBodyForLocation .Locations }} \ No newline at end of file + +func (o Location) IsValid() error { + count := 0 + + switch { + {{- range $key, $location := .Locations}} + case o.{{- camelCase $key}}{{if ne (locationType $key $location true) "bool"}} != nil{{end}}: + {{- range $name, $var := $location.Vars}} + if o.{{camelCase $key}}.{{camelCase $name}} == "" { + return fmt.Errorf("{{camelCase $name}} is unspecified") + } + {{- end}} + count++ + {{- end}} + } + + if count == 0 { + return fmt.Errorf("no path specified") + } + + if count > 1 { + return fmt.Errorf("multiple paths specified: only one should be specified") + } + + return nil +} + +func (o Location) Xpath(vn version.Number, name string) ([]string, error) { + + var ans []string + + switch { + {{- range $key, $location := .Locations}} + case o.{{- camelCase $key}}{{if ne (locationType $key $location true) "bool"}} != nil{{end}}: + {{- range $name, $var := $location.Vars}} + if o.{{camelCase $key}}.{{camelCase $name}} == "" { + return nil, fmt.Errorf("{{camelCase $name}} is unspecified") + } + {{- end}} + ans = []string{ + {{- range $name, $xpath := $location.Xpath}} + {{- if contains $xpath "Entry"}} + {{ asEntryXpath $key $xpath }} + {{- else}} + "{{$xpath}}", + {{- end}} + {{- end}} + } + {{- end}} + default: + return nil, errors.NoLocationSpecifiedError + } + + ans = append(ans, util.AsEntryXpath([]string{name})) + + return ans, nil +} \ No newline at end of file From 2b7514c10f44eeb3e2fd6bb567ec8805ca1e37c3 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 13:07:38 +0100 Subject: [PATCH 12/19] clean code --- pkg/generate/generator.go | 4 +- pkg/generate/generator_test.go | 2 +- pkg/translate/funcs.go | 145 --------------------------------- pkg/translate/structs.go | 54 ------------ 4 files changed, 2 insertions(+), 203 deletions(-) diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go index 8770dfb8..0e433122 100644 --- a/pkg/generate/generator.go +++ b/pkg/generate/generator.go @@ -76,9 +76,7 @@ func (c *Creator) generateOutputFileFromTemplate(tmpl *template.Template, output func (c *Creator) parseTemplate(templateName string) (*template.Template, error) { templatePath := fmt.Sprintf("%s/%s", c.TemplatesDir, templateName) funcMap := template.FuncMap{ - "packageName": translate.PackageName, - "structsDefinitionsForLocation": translate.StructsDefinitionsForLocation, - "funcBodyForLocation": translate.FuncBodyForLocation, + "packageName": translate.PackageName, "camelCase": func(name string) string { return naming.CamelCase("", name, "", true) }, diff --git a/pkg/generate/generator_test.go b/pkg/generate/generator_test.go index 816cc90e..51de2e59 100644 --- a/pkg/generate/generator_test.go +++ b/pkg/generate/generator_test.go @@ -44,7 +44,7 @@ func TestListOfTemplates(t *testing.T) { assert.Equal(t, 4, len(templates)) } -func TestParseTemplate(t *testing.T) { +func TestParseTemplateForInterfaces(t *testing.T) { // given spec := properties.Normalization{ GoSdkPath: []string{"object", "address"}, diff --git a/pkg/translate/funcs.go b/pkg/translate/funcs.go index 36a3212f..9f507c2c 100644 --- a/pkg/translate/funcs.go +++ b/pkg/translate/funcs.go @@ -2,8 +2,6 @@ package translate import ( "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" - "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" - "sort" "strings" ) @@ -13,146 +11,3 @@ func AsEntryXpath(location, xpath string) string { xpath = naming.CamelCase("", xpath, "", true) return "util.AsEntryXpath([]string{o." + location + "." + xpath + "})," } - -func FuncBodyForLocation(locations map[string]*properties.Location) (string, error) { - keys := make([]string, 0, len(locations)) - for key := range locations { - keys = append(keys, key) - } - sort.Strings(keys) - - mapIsValid := map[string]string{ - "shared": ` - case o.Shared: - count++ -`, - - "from_panorama": ` - case o.FromPanorama: - count++ -`, - - "vsys": ` - case o.Vsys != nil: - if o.Vsys.Vsys == "" { - return fmt.Errorf("vsys.vsys is unspecified") - } - if o.Vsys.NgfwDevice == "" { - return fmt.Errorf("vsys.ngfw_device is unspecified") - } - count++ -`, - - "device_group": ` - case o.DeviceGroup != nil: - if o.DeviceGroup.DeviceGroup == "" { - return fmt.Errorf("device_group.device_group is unspecified") - } - if o.DeviceGroup.PanoramaDevice == "" { - return fmt.Errorf("device_group.panorama_device is unspecified") - } - count++ -`, - } - mapXpath := map[string]string{ - "shared": ` - case o.Shared: - ans = []string{ - "config", - "shared", - } -`, - - "from_panorama": ` - case o.FromPanorama: - ans = []string{"config", "panorama"} -`, - - "vsys": ` - case o.Vsys != nil: - if o.Vsys.NgfwDevice == "" { - return nil, fmt.Errorf("NgfwDevice is unspecified") - } - if o.Vsys.Vsys == "" { - return nil, fmt.Errorf("Vsys is unspecified") - } - ans = []string{ - "config", - "devices", - util.AsEntryXpath([]string{o.Vsys.NgfwDevice}), - "vsys", - util.AsEntryXpath([]string{o.Vsys.Vsys}), - } -`, - - "device_group": ` - case o.DeviceGroup != nil: - if o.DeviceGroup.PanoramaDevice == "" { - return nil, fmt.Errorf("PanoramaDevice is unspecified") - } - if o.DeviceGroup.DeviceGroup == "" { - return nil, fmt.Errorf("DeviceGroup is unspecified") - } - ans = []string{ - "config", - "devices", - util.AsEntryXpath([]string{o.DeviceGroup.PanoramaDevice}), - "device-group", - util.AsEntryXpath([]string{o.DeviceGroup.DeviceGroup}), - } -`, - } - - var builder strings.Builder - funcBodyForLocation(&builder, keys, "IsValid", "()", "error", false, - ` count := 0 - - switch { -`, - ` } - - if count == 0 { - return fmt.Errorf("no path specified") - } - - if count > 1 { - return fmt.Errorf("multiple paths specified: only one should be specified") - } - - return nil -`, - mapIsValid) - funcBodyForLocation(&builder, keys, "Xpath", "(vn version.Number, name string)", "([]string, error)", - true, ` - var ans []string - - switch { -`, - ` - default: - return nil, errors.NoLocationSpecifiedError - } - - ans = append(ans, Suffix...) - ans = append(ans, util.AsEntryXpath([]string{name})) - - return ans, nil -`, - mapXpath) - - return builder.String(), nil -} - -func funcBodyForLocation(builder *strings.Builder, keys []string, funcName string, funcInput string, funcOutput string, - startFromNewLine bool, funcBegin string, funcEnd string, funcCases map[string]string) { - if startFromNewLine { - builder.WriteString("\n") - } - builder.WriteString("func (o Location) " + funcName + funcInput + " " + funcOutput + " {\n") - builder.WriteString(funcBegin) - for _, name := range keys { - builder.WriteString(funcCases[name]) - } - builder.WriteString(funcEnd) - builder.WriteString("}\n") -} diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index 35d6e02e..ce477977 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -3,8 +3,6 @@ package translate import ( "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" - "sort" - "strings" ) func LocationType(name string, location properties.Location, pointer bool) string { @@ -26,55 +24,3 @@ func OmitEmpty(location properties.Location) string { return "" } } - -func StructsDefinitionsForLocation(locations map[string]*properties.Location) (string, error) { - keys := make([]string, 0, len(locations)) - for key := range locations { - keys = append(keys, key) - } - sort.Strings(keys) - - var builder strings.Builder - builder.WriteString("type Location struct {\n") - for _, name := range keys { - switch name { - case "shared": - builder.WriteString("\tShared bool `json:\"shared\"`\n") - case "from_panorama": - builder.WriteString("\tFromPanorama bool `json:\"from_panorama\"`\n") - case "vsys": - builder.WriteString("\tVsys *VsysLocation `json:\"vsys,omitempty\"`\n") - case "device_group": - builder.WriteString("\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n") - } - } - builder.WriteString("}\n") - - nestedStructsDefinitionsForLocation(locations, "vsys", "VsysLocation", &builder) - nestedStructsDefinitionsForLocation(locations, "device_group", "DeviceGroupLocation", &builder) - - return builder.String(), nil -} - -func nestedStructsDefinitionsForLocation(locations map[string]*properties.Location, locationName string, structName string, builder *strings.Builder) { - if _, ok := locations[locationName]; ok { - keys := make([]string, 0, len(locations[locationName].Vars)) - for key := range locations[locationName].Vars { - keys = append(keys, key) - } - sort.Strings(keys) - - var namesOriginal, namesCamelCaseWithSpaces []string - for _, name := range keys { - namesOriginal = append(namesOriginal, name) - namesCamelCaseWithSpaces = append(namesCamelCaseWithSpaces, naming.CamelCase("", name, "", true)) - } - namesCamelCaseWithSpaces = MakeIndentationEqual(namesCamelCaseWithSpaces) - - builder.WriteString("\ntype " + structName + " struct {\n") - for idx, name := range namesCamelCaseWithSpaces { - builder.WriteString("\t" + name + " string `json:\"" + namesOriginal[idx] + "\"`\n") - } - builder.WriteString("}\n") - } -} From 5bc88c5ff1a19b7ba99435bda574fabbfdf427a2 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 13:34:52 +0100 Subject: [PATCH 13/19] tests for functions used while generating structs and funcs --- pkg/translate/funcs_test.go | 15 ++++ pkg/translate/names.go | 19 ------ pkg/translate/names_test.go | 12 ---- pkg/translate/structs.go | 4 +- pkg/translate/structs_test.go | 125 +++++++++------------------------- 5 files changed, 48 insertions(+), 127 deletions(-) diff --git a/pkg/translate/funcs_test.go b/pkg/translate/funcs_test.go index c2cb5d52..b6042a98 100644 --- a/pkg/translate/funcs_test.go +++ b/pkg/translate/funcs_test.go @@ -1 +1,16 @@ package translate + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAsEntryXpath(t *testing.T) { + // given + + // when + asEntryXpath := AsEntryXpath("device_group", "{{ Entry $panorama_device }}") + + // then + assert.Equal(t, "util.AsEntryXpath([]string{o.DeviceGroup.PanoramaDevice}),", asEntryXpath) +} diff --git a/pkg/translate/names.go b/pkg/translate/names.go index bd9133ee..3c62684a 100644 --- a/pkg/translate/names.go +++ b/pkg/translate/names.go @@ -1,7 +1,5 @@ package translate -import "strings" - // PackageName Get package name from Go SDK path func PackageName(list []string) string { if len(list) == 0 { @@ -9,20 +7,3 @@ func PackageName(list []string) string { } return list[len(list)-1] } - -// MakeIndentationEqual Check max lenght of the string in the list and then add spaces at the end of very name to make equal indentation -func MakeIndentationEqual(list []string) []string { - maxLength := 0 - - for _, str := range list { - if len(str) > maxLength { - maxLength = len(str) - } - } - - for idx, str := range list { - list[idx] = str + strings.Repeat(" ", maxLength-len(str)) - } - - return list -} diff --git a/pkg/translate/names_test.go b/pkg/translate/names_test.go index 0b4e5d6a..f0a7c2cc 100644 --- a/pkg/translate/names_test.go +++ b/pkg/translate/names_test.go @@ -15,15 +15,3 @@ func TestPackageName(t *testing.T) { // then assert.Equal(t, "address", packageName) } - -func TestMakeIndentationEqual(t *testing.T) { - // given - givenItems := []string{"test", "a"} - expectedItems := []string{"test", "a "} - - // when - changedItems := MakeIndentationEqual(givenItems) - - // then - assert.Equal(t, expectedItems, changedItems) -} diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index ce477977..88eb4fb0 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -5,7 +5,7 @@ import ( "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" ) -func LocationType(name string, location properties.Location, pointer bool) string { +func LocationType(name string, location *properties.Location, pointer bool) string { prefix := "" if pointer { prefix = "*" @@ -17,7 +17,7 @@ func LocationType(name string, location properties.Location, pointer bool) strin } } -func OmitEmpty(location properties.Location) string { +func OmitEmpty(location *properties.Location) string { if location.Vars != nil { return ",omitempty" } else { diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go index 6a2f4071..4b7de4a4 100644 --- a/pkg/translate/structs_test.go +++ b/pkg/translate/structs_test.go @@ -6,9 +6,7 @@ import ( "testing" ) -func TestStructsDefinitionsForLocation(t *testing.T) { - // given - var sampleSpec = `name: 'Address' +const sampleSpec = `name: 'Address' terraform_provider_suffix: 'address' go_sdk_path: - 'objects' @@ -22,33 +20,6 @@ locations: panorama: true ngfw: true xpath: ['config', 'shared'] - 'from_panorama': - description: 'Located in the config pushed from Panorama.' - read_only: true - device: - ngfw: true - xpath: ['config', 'panorama'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true - xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' 'device_group': description: 'Located in a specific device group.' device: @@ -76,74 +47,40 @@ entry: min: 1 max: 63 version: '10.1.0' -spec: - params: - description: - description: 'The description.' - type: 'string' - length: - min: 0 - max: 1023 - profiles: - - - xpath: ["description"] - tags: - description: 'The administrative tags.' - type: 'list' - count: - max: 64 - items: - type: 'string' - length: - max: 127 - profiles: - - - type: 'member' - xpath: ["tag"] - one_of: - 'ip_netmask': - description: 'The IP netmask value.' - profiles: - - - xpath: ["ip-netmask"] - 'ip_range': - description: 'The IP range value.' - profiles: - - - xpath: ["ip-range"] - 'fqdn': - description: 'The FQDN value.' - regex: '^[a-zA-Z0-9_]([a-zA-Z0-9:_-])+[a-zA-Z0-9]$' - length: - min: 1 - max: 255 - profiles: - - - xpath: ["fqdn"] - 'ip_wildcard': - description: 'The IP wildcard value.' - profiles: - - - xpath: ["ip-wildcard"] ` - var expectedStructsForLocation = "type Location struct {\n" + - "\tDeviceGroup *DeviceGroupLocation `json:\"device_group,omitempty\"`\n" + - "\tFromPanorama bool `json:\"from_panorama\"`\n" + - "\tShared bool `json:\"shared\"`\n" + - "\tVsys *VsysLocation `json:\"vsys,omitempty\"`\n" + - "}\n" + - "\ntype VsysLocation struct {\n" + - "\tNgfwDevice string `json:\"ngfw_device\"`\n" + - "\tVsys string `json:\"vsys\"`\n}\n" + - "\ntype DeviceGroupLocation struct {\n" + - "\tDeviceGroup string `json:\"device_group\"`\n" + - "\tPanoramaDevice string `json:\"panorama_device\"`\n" + - "}\n" + +func TestLocationType(t *testing.T) { + // given + yamlParsedData, _ := properties.ParseSpec([]byte(sampleSpec)) + locationKeys := []string{"device_group", "shared"} + locations := yamlParsedData.Locations + var locationTypes []string // when + for _, locationKey := range locationKeys { + locationTypes = append(locationTypes, LocationType(locationKey, locations[locationKey], true)) + } + + // then + assert.NotEmpty(t, locationTypes) + assert.Contains(t, locationTypes, "*DeviceGroupLocation") + assert.Contains(t, locationTypes, "bool") +} + +func TestOmitEmpty(t *testing.T) { + // given yamlParsedData, _ := properties.ParseSpec([]byte(sampleSpec)) - structsForLocation, _ := StructsDefinitionsForLocation(yamlParsedData.Locations) + locationKeys := []string{"device_group", "shared"} + locations := yamlParsedData.Locations + var omitEmptyLocations []string + + // when + for _, locationKey := range locationKeys { + omitEmptyLocations = append(omitEmptyLocations, OmitEmpty(locations[locationKey])) + } // then - assert.Equal(t, expectedStructsForLocation, structsForLocation) + assert.NotEmpty(t, omitEmptyLocations) + assert.Contains(t, omitEmptyLocations, ",omitempty") + assert.Contains(t, omitEmptyLocations, "") } From d9fdd835cea6de557218bcd258a7ae6ffde22240 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 13:47:12 +0100 Subject: [PATCH 14/19] fix issues after tests --- specs/panorama/device-group.yaml | 10 ++++++++++ specs/panorama/template-stack.yaml | 10 ++++++++++ specs/panorama/template.yaml | 10 ++++++++++ specs/policies/security-policy-rule.yaml | 2 +- templates/sdk/location.tmpl | 4 +--- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/specs/panorama/device-group.yaml b/specs/panorama/device-group.yaml index cb3defc6..9fd5b545 100644 --- a/specs/panorama/device-group.yaml +++ b/specs/panorama/device-group.yaml @@ -16,6 +16,16 @@ locations: - '{{ Entry $ngfw_device }}' - 'vsys' - '{{ Entry $vsys }}' + vars: + 'ngfw_device': + description: 'The NGFW device.' + default: 'localhost.localdomain' + 'vsys': + description: 'The vsys.' + default: 'vsys1' + validation: + not_values: + 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' entry: name: description: 'The name of the device group.' diff --git a/specs/panorama/template-stack.yaml b/specs/panorama/template-stack.yaml index 30eb3c3f..680a1e5d 100644 --- a/specs/panorama/template-stack.yaml +++ b/specs/panorama/template-stack.yaml @@ -16,6 +16,16 @@ locations: - '{{ Entry $ngfw_device }}' - 'vsys' - '{{ Entry $vsys }}' + vars: + 'ngfw_device': + description: 'The NGFW device.' + default: 'localhost.localdomain' + 'vsys': + description: 'The vsys.' + default: 'vsys1' + validation: + not_values: + 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' entry: name: description: 'The name of the template stack.' diff --git a/specs/panorama/template.yaml b/specs/panorama/template.yaml index cb2b31aa..6183a30c 100644 --- a/specs/panorama/template.yaml +++ b/specs/panorama/template.yaml @@ -16,6 +16,16 @@ locations: - '{{ Entry $ngfw_device }}' - 'vsys' - '{{ Entry $vsys }}' + vars: + 'ngfw_device': + description: 'The NGFW device.' + default: 'localhost.localdomain' + 'vsys': + description: 'The vsys.' + default: 'vsys1' + validation: + not_values: + 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' entry: name: description: 'The name of the template.' diff --git a/specs/policies/security-policy-rule.yaml b/specs/policies/security-policy-rule.yaml index 7319b3dd..e7bb344a 100644 --- a/specs/policies/security-policy-rule.yaml +++ b/specs/policies/security-policy-rule.yaml @@ -2,7 +2,7 @@ name: 'Security policy rule' terraform_provider_suffix: 'security_policy_rule' go_sdk_path: - 'policies' - - 'security-policy-rule' + - 'security_policy_rule' xpath_suffix: - 'security' - 'rules' diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index b229a1c2..a0379982 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -20,10 +20,8 @@ type {{locationType $key $location false}} struct { {{camelCase $key}} string `json:"{{$key}}"` {{- end}} } +{{end}} {{- end}} -{{- end}} - - func (o Location) IsValid() error { count := 0 From f1f2525c25bd436728e9dc9cc3bc86e172155e2f Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Tue, 5 Mar 2024 14:20:49 +0100 Subject: [PATCH 15/19] remove not required spaces from templates --- templates/sdk/entry.tmpl | 2 +- templates/sdk/interfaces.tmpl | 2 +- templates/sdk/location.tmpl | 4 ++-- templates/sdk/service.tmpl | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/sdk/entry.tmpl b/templates/sdk/entry.tmpl index 7f410c4c..3b3d1518 100644 --- a/templates/sdk/entry.tmpl +++ b/templates/sdk/entry.tmpl @@ -1 +1 @@ -package {{ packageName .GoSdkPath }} \ No newline at end of file +package {{packageName .GoSdkPath}} \ No newline at end of file diff --git a/templates/sdk/interfaces.tmpl b/templates/sdk/interfaces.tmpl index 00a72dcc..c886baa1 100644 --- a/templates/sdk/interfaces.tmpl +++ b/templates/sdk/interfaces.tmpl @@ -1,4 +1,4 @@ -package {{ packageName .GoSdkPath }} +package {{packageName .GoSdkPath}} type Specifier func(Entry) (any, error) diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index a0379982..c5b01387 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -1,4 +1,4 @@ -package {{packageName .GoSdkPath }} +package {{packageName .GoSdkPath}} import ( "fmt" @@ -63,7 +63,7 @@ func (o Location) Xpath(vn version.Number, name string) ([]string, error) { ans = []string{ {{- range $name, $xpath := $location.Xpath}} {{- if contains $xpath "Entry"}} - {{ asEntryXpath $key $xpath }} + {{asEntryXpath $key $xpath}} {{- else}} "{{$xpath}}", {{- end}} diff --git a/templates/sdk/service.tmpl b/templates/sdk/service.tmpl index 7f410c4c..3b3d1518 100644 --- a/templates/sdk/service.tmpl +++ b/templates/sdk/service.tmpl @@ -1 +1 @@ -package {{ packageName .GoSdkPath }} \ No newline at end of file +package {{packageName .GoSdkPath}} \ No newline at end of file From b2fb71462a3623317e1ea48d056c6064358e0542 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Wed, 6 Mar 2024 09:23:23 +0100 Subject: [PATCH 16/19] introduce new struct NameVariant for Location names and variables, get rid of camelCase function from template --- pkg/generate/generator.go | 6 +--- pkg/properties/normalized.go | 47 +++++++++++++++++++++++++++++-- pkg/properties/normalized_test.go | 24 ++++++++++++++++ pkg/translate/funcs.go | 1 - pkg/translate/funcs_test.go | 2 +- pkg/translate/structs.go | 5 ++-- pkg/translate/structs_test.go | 2 +- templates/sdk/location.tmpl | 20 ++++++------- 8 files changed, 83 insertions(+), 24 deletions(-) diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go index 0e433122..9d923931 100644 --- a/pkg/generate/generator.go +++ b/pkg/generate/generator.go @@ -2,7 +2,6 @@ package generate import ( "fmt" - "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" "github.com/paloaltonetworks/pan-os-codegen/pkg/translate" "io" @@ -76,10 +75,7 @@ func (c *Creator) generateOutputFileFromTemplate(tmpl *template.Template, output func (c *Creator) parseTemplate(templateName string) (*template.Template, error) { templatePath := fmt.Sprintf("%s/%s", c.TemplatesDir, templateName) funcMap := template.FuncMap{ - "packageName": translate.PackageName, - "camelCase": func(name string) string { - return naming.CamelCase("", name, "", true) - }, + "packageName": translate.PackageName, "locationType": translate.LocationType, "omitEmpty": translate.OmitEmpty, "contains": func(full, part string) bool { diff --git a/pkg/properties/normalized.go b/pkg/properties/normalized.go index 2d99d67e..936fceeb 100644 --- a/pkg/properties/normalized.go +++ b/pkg/properties/normalized.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "github.com/paloaltonetworks/pan-os-codegen/pkg/content" + "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "io/fs" "path/filepath" "runtime" @@ -21,7 +22,13 @@ type Normalization struct { Spec *Spec `json:"spec" yaml:"spec"` } +type NameVariant struct { + Underscore string + CamelCase string +} + type Location struct { + Name *NameVariant Description string `json:"description" yaml:"description"` Device *LocationDevice `json:"device" yaml:"device"` Xpath []string `json:"xpath" yaml:"xpath"` @@ -35,6 +42,7 @@ type LocationDevice struct { } type LocationVar struct { + Name *NameVariant Description string `json:"description" yaml:"description"` Required bool `json:"required" yaml:"required"` Validation *LocationVarValidation `json:"validation" yaml:"validation"` @@ -128,9 +136,31 @@ func GetNormalizations() ([]string, error) { } func ParseSpec(input []byte) (*Normalization, error) { - var ans Normalization - err := content.Unmarshal(input, &ans) - return &ans, err + var spec Normalization + + err := content.Unmarshal(input, &spec) + + err = spec.AddNameVariants() + + return &spec, err +} + +func (spec *Normalization) AddNameVariants() error { + for key, location := range spec.Locations { + location.Name = &NameVariant{ + Underscore: key, + CamelCase: naming.CamelCase("", key, "", true), + } + + for subkey, variable := range location.Vars { + variable.Name = &NameVariant{ + Underscore: subkey, + CamelCase: naming.CamelCase("", subkey, "", true), + } + } + } + + return nil } func (spec *Normalization) Sanity() error { @@ -167,3 +197,14 @@ func (spec *Normalization) Validate() []error { return checks } + +//func (spec *Normalization) GetCamelCaseLocations() map[string]*Location { +// locations := map[string]*Location{} +// +// for key, location := range spec.Locations { +// camelCaseKey := naming.CamelCase("", key, "", true) +// locations[camelCaseKey] = location +// } +// +// return locations +//} diff --git a/pkg/properties/normalized_test.go b/pkg/properties/normalized_test.go index b6a01fb3..7d3a8b72 100644 --- a/pkg/properties/normalized_test.go +++ b/pkg/properties/normalized_test.go @@ -154,6 +154,9 @@ xpath_suffix: - address locations: device_group: + name: + underscore: device_group + camelcase: DeviceGroup description: Located in a specific device group. device: panorama: true @@ -167,16 +170,25 @@ locations: read_only: false vars: device_group: + name: + underscore: device_group + camelcase: DeviceGroup description: The device group. required: true validation: not_values: shared: The device group cannot be "shared". Use the "shared" path instead. panorama_device: + name: + underscore: panorama_device + camelcase: PanoramaDevice description: The panorama device. required: false validation: null from_panorama: + name: + underscore: from_panorama + camelcase: FromPanorama description: Located in the config pushed from Panorama. device: panorama: false @@ -187,6 +199,9 @@ locations: read_only: true vars: {} shared: + name: + underscore: shared + camelcase: Shared description: Located in shared. device: panorama: true @@ -197,6 +212,9 @@ locations: read_only: false vars: {} vsys: + name: + underscore: vsys + camelcase: Vsys description: Located in a specific vsys. device: panorama: true @@ -210,10 +228,16 @@ locations: read_only: false vars: ngfw_device: + name: + underscore: ngfw_device + camelcase: NgfwDevice description: The NGFW device. required: false validation: null vsys: + name: + underscore: vsys + camelcase: Vsys description: The vsys. required: false validation: diff --git a/pkg/translate/funcs.go b/pkg/translate/funcs.go index 9f507c2c..10b04a4a 100644 --- a/pkg/translate/funcs.go +++ b/pkg/translate/funcs.go @@ -6,7 +6,6 @@ import ( ) func AsEntryXpath(location, xpath string) string { - location = naming.CamelCase("", location, "", true) xpath = strings.TrimSpace(strings.Split(strings.Split(xpath, "$")[1], "}")[0]) xpath = naming.CamelCase("", xpath, "", true) return "util.AsEntryXpath([]string{o." + location + "." + xpath + "})," diff --git a/pkg/translate/funcs_test.go b/pkg/translate/funcs_test.go index b6042a98..a47ede8a 100644 --- a/pkg/translate/funcs_test.go +++ b/pkg/translate/funcs_test.go @@ -9,7 +9,7 @@ func TestAsEntryXpath(t *testing.T) { // given // when - asEntryXpath := AsEntryXpath("device_group", "{{ Entry $panorama_device }}") + asEntryXpath := AsEntryXpath("DeviceGroup", "{{ Entry $panorama_device }}") // then assert.Equal(t, "util.AsEntryXpath([]string{o.DeviceGroup.PanoramaDevice}),", asEntryXpath) diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index 88eb4fb0..33e21fb4 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -1,17 +1,16 @@ package translate import ( - "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" ) -func LocationType(name string, location *properties.Location, pointer bool) string { +func LocationType(location *properties.Location, pointer bool) string { prefix := "" if pointer { prefix = "*" } if location.Vars != nil { - return prefix + naming.CamelCase("", name, "", true) + "Location" + return prefix + location.Name.CamelCase + "Location" } else { return "bool" } diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go index 4b7de4a4..6bd61b31 100644 --- a/pkg/translate/structs_test.go +++ b/pkg/translate/structs_test.go @@ -58,7 +58,7 @@ func TestLocationType(t *testing.T) { // when for _, locationKey := range locationKeys { - locationTypes = append(locationTypes, LocationType(locationKey, locations[locationKey], true)) + locationTypes = append(locationTypes, LocationType(locations[locationKey], true)) } // then diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index c5b01387..cdc57075 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -10,14 +10,14 @@ import ( type Location struct { {{range $key, $location := .Locations}} - {{- camelCase $key}} {{locationType $key $location true}} `json:"{{$key}}{{omitEmpty $location}}"` + {{- $location.Name.CamelCase }} {{locationType $location true}} `json:"{{$location.Name.Underscore}}{{omitEmpty $location}}"` {{end}} } {{range $key, $location := .Locations}} {{- if $location.Vars}} -type {{locationType $key $location false}} struct { +type {{locationType $location false}} struct { {{- range $key, $var := $location.Vars}} - {{camelCase $key}} string `json:"{{$key}}"` + {{$var.Name.CamelCase}} string `json:"{{$var.Name.Underscore}}"` {{- end}} } {{end}} @@ -27,10 +27,10 @@ func (o Location) IsValid() error { switch { {{- range $key, $location := .Locations}} - case o.{{- camelCase $key}}{{if ne (locationType $key $location true) "bool"}} != nil{{end}}: + case o.{{- $location.Name.CamelCase}}{{if ne (locationType $location true) "bool"}} != nil{{end}}: {{- range $name, $var := $location.Vars}} - if o.{{camelCase $key}}.{{camelCase $name}} == "" { - return fmt.Errorf("{{camelCase $name}} is unspecified") + if o.{{$location.Name.CamelCase}}.{{$var.Name.CamelCase}} == "" { + return fmt.Errorf("{{$var.Name.CamelCase}} is unspecified") } {{- end}} count++ @@ -54,16 +54,16 @@ func (o Location) Xpath(vn version.Number, name string) ([]string, error) { switch { {{- range $key, $location := .Locations}} - case o.{{- camelCase $key}}{{if ne (locationType $key $location true) "bool"}} != nil{{end}}: + case o.{{- $location.Name.CamelCase}}{{if ne (locationType $location true) "bool"}} != nil{{end}}: {{- range $name, $var := $location.Vars}} - if o.{{camelCase $key}}.{{camelCase $name}} == "" { - return nil, fmt.Errorf("{{camelCase $name}} is unspecified") + if o.{{$location.Name.CamelCase}}.{{$var.Name.CamelCase}} == "" { + return nil, fmt.Errorf("{{$var.Name.CamelCase}} is unspecified") } {{- end}} ans = []string{ {{- range $name, $xpath := $location.Xpath}} {{- if contains $xpath "Entry"}} - {{asEntryXpath $key $xpath}} + {{asEntryXpath $location.Name.CamelCase $xpath}} {{- else}} "{{$xpath}}", {{- end}} From b535826b5ea0bcd5956088016e6c49c1c1a371ff Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Wed, 6 Mar 2024 09:50:07 +0100 Subject: [PATCH 17/19] Change Go SDK path for security policy rule --- specs/policies/security-policy-rule.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/policies/security-policy-rule.yaml b/specs/policies/security-policy-rule.yaml index e7bb344a..978fa99d 100644 --- a/specs/policies/security-policy-rule.yaml +++ b/specs/policies/security-policy-rule.yaml @@ -2,7 +2,8 @@ name: 'Security policy rule' terraform_provider_suffix: 'security_policy_rule' go_sdk_path: - 'policies' - - 'security_policy_rule' + - 'rules' + - 'security' xpath_suffix: - 'security' - 'rules' From 54f99e30ff3ae5ffffdf7e2fb89e9e05c199bab7 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Wed, 6 Mar 2024 15:04:28 +0100 Subject: [PATCH 18/19] change go sdk path for service and address group --- pkg/properties/normalized.go | 11 ----------- specs/objects/address-group.yaml | 3 ++- specs/objects/service-group.yaml | 3 ++- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/pkg/properties/normalized.go b/pkg/properties/normalized.go index 936fceeb..c2861620 100644 --- a/pkg/properties/normalized.go +++ b/pkg/properties/normalized.go @@ -197,14 +197,3 @@ func (spec *Normalization) Validate() []error { return checks } - -//func (spec *Normalization) GetCamelCaseLocations() map[string]*Location { -// locations := map[string]*Location{} -// -// for key, location := range spec.Locations { -// camelCaseKey := naming.CamelCase("", key, "", true) -// locations[camelCaseKey] = location -// } -// -// return locations -//} diff --git a/specs/objects/address-group.yaml b/specs/objects/address-group.yaml index 830eb3ca..90005d15 100644 --- a/specs/objects/address-group.yaml +++ b/specs/objects/address-group.yaml @@ -2,7 +2,8 @@ name: 'Address group' terraform_provider_suffix: 'address_group' go_sdk_path: - 'objects' - - 'address_group' + - 'address' + - 'group' xpath_suffix: - 'address-group' locations: diff --git a/specs/objects/service-group.yaml b/specs/objects/service-group.yaml index 5fc79909..adbadf0b 100644 --- a/specs/objects/service-group.yaml +++ b/specs/objects/service-group.yaml @@ -2,7 +2,8 @@ name: 'Service group' terraform_provider_suffix: 'service_group' go_sdk_path: - 'objects' - - 'service_group' + - 'service' + - 'group' xpath_suffix: - 'service-group' locations: From 96e300a15e6af5b0fb29daf4776fc37c26af70e7 Mon Sep 17 00:00:00 2001 From: Sebastian Czech Date: Fri, 8 Mar 2024 09:02:48 +0100 Subject: [PATCH 19/19] add error handling for func AsEntryXpath --- pkg/translate/funcs.go | 8 ++++++-- pkg/translate/funcs_test.go | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/translate/funcs.go b/pkg/translate/funcs.go index 10b04a4a..ec03252c 100644 --- a/pkg/translate/funcs.go +++ b/pkg/translate/funcs.go @@ -1,12 +1,16 @@ package translate import ( + "errors" "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" "strings" ) -func AsEntryXpath(location, xpath string) string { +func AsEntryXpath(location, xpath string) (string, error) { + if !strings.Contains(xpath, "$") || !strings.Contains(xpath, "}") { + return "", errors.New("$ followed by } should exists in xpath'") + } xpath = strings.TrimSpace(strings.Split(strings.Split(xpath, "$")[1], "}")[0]) xpath = naming.CamelCase("", xpath, "", true) - return "util.AsEntryXpath([]string{o." + location + "." + xpath + "})," + return "util.AsEntryXpath([]string{o." + location + "." + xpath + "}),", nil } diff --git a/pkg/translate/funcs_test.go b/pkg/translate/funcs_test.go index a47ede8a..fdb891ee 100644 --- a/pkg/translate/funcs_test.go +++ b/pkg/translate/funcs_test.go @@ -9,7 +9,7 @@ func TestAsEntryXpath(t *testing.T) { // given // when - asEntryXpath := AsEntryXpath("DeviceGroup", "{{ Entry $panorama_device }}") + asEntryXpath, _ := AsEntryXpath("DeviceGroup", "{{ Entry $panorama_device }}") // then assert.Equal(t, "util.AsEntryXpath([]string{o.DeviceGroup.PanoramaDevice}),", asEntryXpath)