diff --git a/assets/errors/panos.go b/assets/errors/panos.go index b56e8c49..b2e5b3c9 100644 --- a/assets/errors/panos.go +++ b/assets/errors/panos.go @@ -12,8 +12,10 @@ import ( var InvalidFilterError = stderr.New("filter is improperly formatted") var NameNotSpecifiedError = stderr.New("name is not specified") var NoLocationSpecifiedError = stderr.New("no location specified") +var RelativePositionWithRemoveEverythingElseError = stderr.New("cannot do relative positioning when removing all other rules") var UnrecognizedOperatorError = stderr.New("unsupported filter operator") var UnsupportedFilterTypeError = stderr.New("unsupported type for filtering") +var UuidNotSpecifiedError = stderr.New("uuid is not specified") // Panos is an error returned from PAN-OS. // diff --git a/assets/sdk/xmlapiclient.go b/assets/sdk/xmlapiclient.go index 75a01f58..cfae6e9f 100644 --- a/assets/sdk/xmlapiclient.go +++ b/assets/sdk/xmlapiclient.go @@ -898,14 +898,14 @@ func (c *XmlApiClient) ImportFile(ctx context.Context, cmd *xmlapi.Import, conte } // ExportFile retrieves a file from PAN-OS. -func (c *XmlApiClient) ExportFile(ctx context.Context, cmd *xmlapi.Export, ans any) (string, []byte, error) { +func (c *XmlApiClient) ExportFile(ctx context.Context, cmd *xmlapi.Export, ans any) (string, []byte, *http.Response, error) { if cmd == nil { - return "", nil, fmt.Errorf("cmd is nil") + return "", nil, nil, fmt.Errorf("cmd is nil") } data, err := cmd.AsUrlValues() if err != nil { - return "", nil, err + return "", nil, nil, err } if c.ApiKeyInRequest && c.ApiKey != "" && data.Get("key") == "" { @@ -914,12 +914,12 @@ func (c *XmlApiClient) ExportFile(ctx context.Context, cmd *xmlapi.Export, ans a req, err := http.NewRequestWithContext(ctx, "POST", c.api_url, strings.NewReader(data.Encode())) if err != nil { - return "", nil, err + return "", nil, nil, err } b, resp, err := c.sendRequest(ctx, req, false, ans) if err != nil { - return "", b, err + return "", b, resp, err } var filename string @@ -928,7 +928,7 @@ func (c *XmlApiClient) ExportFile(ctx context.Context, cmd *xmlapi.Export, ans a filename = params["filename"] } - return filename, b, nil + return filename, b, resp, nil } // GetTechSupportFile returns the tech support file .tgz file. @@ -950,7 +950,7 @@ func (c *XmlApiClient) GetTechSupportFile(ctx context.Context) (string, []byte, for { resp = util.BasicJob{} - if _, _, err = c.ExportFile(ctx, cmd, &resp); err != nil { + if _, _, _, err = c.ExportFile(ctx, cmd, &resp); err != nil { return "", nil, err } @@ -974,7 +974,7 @@ func (c *XmlApiClient) GetTechSupportFile(ctx context.Context) (string, []byte, cmd.Action = "get" - filename, b, err := c.ExportFile(ctx, cmd, nil) + filename, b, _, err := c.ExportFile(ctx, cmd, nil) return filename, b, err } @@ -1036,8 +1036,6 @@ func (c *XmlApiClient) sendRequest(ctx context.Context, req *http.Request, strip } } - // log.Printf("REPLY: %s\n", string(body)) - if ans == nil { return body, resp, nil } diff --git a/assets/util/comparison.go b/assets/util/comparison.go index e5c164b7..2e77f5c3 100644 --- a/assets/util/comparison.go +++ b/assets/util/comparison.go @@ -61,7 +61,7 @@ func TargetsMatch(a, b map[string][]string) bool { return true } -func OptionalStringsMatch(a, b *string) bool { +func StringsMatch(a, b *string) bool { if a == nil && b == nil { return true } else if a == nil || b == nil { @@ -71,6 +71,44 @@ func OptionalStringsMatch(a, b *string) bool { return *a == *b } -func StringsMatch(a, b string) bool { - return a == b +func BoolsMatch(a, b *bool) bool { + if a == nil && b == nil { + return true + } else if a == nil || b == nil { + return false + } + + return *a == *b +} + +func FloatsMatch(a, b *float64) bool { + if a == nil && b == nil { + return true + } else if a == nil || b == nil { + return false + } + + return *a == *b +} + +func IntsMatch(a, b *int64) bool { + if a == nil && b == nil { + return true + } else if a == nil || b == nil { + return false + } + + return *a == *b +} + +func AnysMatch(a, b any) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + return true } diff --git a/assets/util/pangoclient.go b/assets/util/pangoclient.go index b7b95c05..5934d5fa 100644 --- a/assets/util/pangoclient.go +++ b/assets/util/pangoclient.go @@ -34,7 +34,7 @@ type PangoClient interface { // Specialized communication functions around specific XPI API commands. MultiConfig(context.Context, *xmlapi.MultiConfig, bool, url.Values) ([]byte, *http.Response, *xmlapi.MultiConfigResponse, error) ImportFile(context.Context, *xmlapi.Import, string, string, string, bool, any) ([]byte, *http.Response, error) - ExportFile(context.Context, *xmlapi.Export, any) (string, []byte, error) + ExportFile(context.Context, *xmlapi.Export, any) (string, []byte, *http.Response, error) // Operational functions in use by one or more resources / data sources / namespaces. RequestPasswordHash(context.Context, string) (string, error) diff --git a/assets/util/types.go b/assets/util/types.go new file mode 100644 index 00000000..67773a45 --- /dev/null +++ b/assets/util/types.go @@ -0,0 +1,23 @@ +package util + +// For reference: https://github.com/golang/go/issues/45624 + +// Bool returns a pointer to the given bool. +func Bool(v bool) *bool { + return &v +} + +// Int returns a pointer to the given int64. +func Int(v int64) *int64 { + return &v +} + +// Float returns a pointer to the given float64. +func Float(v float64) *float64 { + return &v +} + +// String returns a pointer to the given string. +func String(v string) *string { + return &v +} diff --git a/assets/util/util.go b/assets/util/util.go index 2a21a3e3..2957062a 100644 --- a/assets/util/util.go +++ b/assets/util/util.go @@ -108,6 +108,11 @@ func AsEntryXpath(vals []string) string { return buf.String() } +// AsUuidXpath returns an xpath segment as a UUID location. +func AsUuidXpath(v string) string { + return fmt.Sprintf("entry[@uuid='%s']", v) +} + // AsMemberXpath returns the given values as a member xpath segment. func AsMemberXpath(vals []string) string { var buf bytes.Buffer diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go index 99a2aba3..c623bb00 100644 --- a/pkg/generate/generator.go +++ b/pkg/generate/generator.go @@ -119,6 +119,7 @@ func (c *Creator) createFile(filePath string) (*os.File, error) { func (c *Creator) parseTemplate(templateName string) (*template.Template, error) { templatePath := filepath.Join(c.TemplatesDir, templateName) funcMap := template.FuncMap{ + "renderImports": translate.RenderImports, "packageName": translate.PackageName, "locationType": translate.LocationType, "specParamType": translate.SpecParamType, diff --git a/pkg/translate/funcs.go b/pkg/translate/funcs.go index 1d8fb9ab..4fc15d83 100644 --- a/pkg/translate/funcs.go +++ b/pkg/translate/funcs.go @@ -145,7 +145,7 @@ func specMatchFunctionName(parent []string, param *properties.SpecParam) string if param.Type == "list" { return "util.OrderedListsMatch" } else if param.Type == "string" { - return "util.OptionalStringsMatch" + return "util.StringsMatch" } else { return fmt.Sprintf("specMatch%s%s", strings.Join(parent, ""), param.Name.CamelCase) } diff --git a/pkg/translate/funcs_test.go b/pkg/translate/funcs_test.go index 328bb066..abba6d1c 100644 --- a/pkg/translate/funcs_test.go +++ b/pkg/translate/funcs_test.go @@ -173,7 +173,7 @@ func TestSpecMatchesFunction(t *testing.T) { calculatedSpecMatchFunctionListString := SpecMatchesFunction(¶mTypeListString) // then - assert.Equal(t, "util.OptionalStringsMatch", calculatedSpecMatchFunctionString) + assert.Equal(t, "util.StringsMatch", calculatedSpecMatchFunctionString) assert.Equal(t, "util.OrderedListsMatch", calculatedSpecMatchFunctionListString) } diff --git a/pkg/translate/imports.go b/pkg/translate/imports.go new file mode 100644 index 00000000..459195cf --- /dev/null +++ b/pkg/translate/imports.go @@ -0,0 +1,31 @@ +package translate + +import "github.com/paloaltonetworks/pan-os-codegen/pkg/imports" + +func RenderImports(templateType string) (string, error) { + manager := imports.NewManager() + + switch templateType { + case "entry": + manager.AddStandardImport("encoding/xml", "") + manager.AddStandardImport("fmt", "") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/filtering", "filtering") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/generic", "generic") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/util", "util") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/version", "version") + case "location": + manager.AddStandardImport("fmt", "") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/errors", "errors") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/util", "util") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/version", "version") + case "service": + manager.AddStandardImport("context", "") + manager.AddStandardImport("fmt", "") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/errors", "errors") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/filtering", "filtering") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/util", "util") + manager.AddSdkImport("github.com/PaloAltoNetworks/pango/xmlapi", "xmlapi") + } + + return manager.RenderImports() +} diff --git a/pkg/translate/imports_test.go b/pkg/translate/imports_test.go new file mode 100644 index 00000000..5c1456e4 --- /dev/null +++ b/pkg/translate/imports_test.go @@ -0,0 +1,25 @@ +package translate + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestRenderImports(t *testing.T) { + // given + expectedImports := ` +import ( + "fmt" + + errors "github.com/PaloAltoNetworks/pango/errors" + util "github.com/PaloAltoNetworks/pango/util" + version "github.com/PaloAltoNetworks/pango/version" +)` + + // when + actualImports, _ := RenderImports("location") + + // then + assert.NotNil(t, actualImports) + assert.Equal(t, expectedImports, actualImports) +} diff --git a/templates/sdk/entry.tmpl b/templates/sdk/entry.tmpl index 1d84ba12..2581c36e 100644 --- a/templates/sdk/entry.tmpl +++ b/templates/sdk/entry.tmpl @@ -1,15 +1,7 @@ {{- if .Entry}} package {{packageName .GoSdkPath}} - import ( - "encoding/xml" - "fmt" - - "github.com/PaloAltoNetworks/pango/filtering" - "github.com/PaloAltoNetworks/pango/generic" - "github.com/PaloAltoNetworks/pango/util" - "github.com/PaloAltoNetworks/pango/version" - ) + {{renderImports "entry"}} var ( _ filtering.Fielder = &Entry{} diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl index e23bebde..3323db24 100644 --- a/templates/sdk/location.tmpl +++ b/templates/sdk/location.tmpl @@ -1,12 +1,6 @@ package {{packageName .GoSdkPath}} -import ( -"fmt" - -"github.com/PaloAltoNetworks/pango/errors" -"github.com/PaloAltoNetworks/pango/util" -"github.com/PaloAltoNetworks/pango/version" -) +{{renderImports "location"}} type Location struct { {{range $key, $location := .Locations}} diff --git a/templates/sdk/service.tmpl b/templates/sdk/service.tmpl index a81358bc..0c43541c 100644 --- a/templates/sdk/service.tmpl +++ b/templates/sdk/service.tmpl @@ -1,14 +1,6 @@ package {{packageName .GoSdkPath}} {{- if .Entry}} - import ( - "context" - "fmt" - - "github.com/PaloAltoNetworks/pango/errors" - "github.com/PaloAltoNetworks/pango/filtering" - "github.com/PaloAltoNetworks/pango/util" - "github.com/PaloAltoNetworks/pango/xmlapi" - ) + {{renderImports "service"}} type Service struct { client util.PangoClient @@ -155,6 +147,7 @@ package {{packageName .GoSdkPath}} Action: "rename", Xpath: util.AsXpath(path), NewName: entry.Name, + Target: s.client.GetTarget(), }) } else { old, err = s.Read(ctx, loc, entry.Name, "get") @@ -178,6 +171,7 @@ package {{packageName .GoSdkPath}} Action: "edit", Xpath: util.AsXpath(path), Element: updateSpec, + Target: s.client.GetTarget(), }) } @@ -357,6 +351,7 @@ package {{packageName .GoSdkPath}} Action: "edit", Xpath: util.AsXpath(path), Element: elm, + Target: s.client.GetTarget(), }) } break @@ -378,6 +373,7 @@ package {{packageName .GoSdkPath}} Action: "set", Xpath: util.AsXpath(path), Element: elm, + Target: s.client.GetTarget(), }) } }