Skip to content

feat(specs): Add codegen spec and acceptance tests for ethernet layer3 subinterface #488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions assets/pango/errors/panos.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

var ObjectExists = stderr.New("object already exists")
var InvalidFilterError = stderr.New("filter is improperly formatted")
var NameNotSpecifiedError = stderr.New("name is not specified")
var NoLocationSpecifiedError = stderr.New("no location specified")
Expand Down Expand Up @@ -151,3 +152,17 @@ func (e *errorCheck) CodeError() string {
return fmt.Sprintf("(%d) Unknown failure code, operation failed", e.Code)
}
}

type InvalidXpathComponentError struct {
Message string
}

func (o InvalidXpathComponentError) Error() string {
return o.Message
}

func NewInvalidXpathComponentError(message string) *InvalidXpathComponentError {
return &InvalidXpathComponentError{
Message: message,
}
}
35 changes: 2 additions & 33 deletions assets/pango/example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"encoding/xml"
"fmt"
"log"

Expand Down Expand Up @@ -671,8 +670,8 @@ func checkSecurityPolicyRules(c *pango.Client, ctx context.Context) {
log.Printf("Security policy rule '%s:%s' with description '%s' read by id", *securityPolicyRuleReply.Uuid, securityPolicyRuleReply.Name, *securityPolicyRuleReply.Description)

// SECURITY POLICY RULE - UPDATE 2
securityPolicyRuleEntry.Description = util.String("changed by id description")
securityPolicyRuleReply, err = securityPolicyRuleApi.UpdateById(ctx, *securityPolicyRuleLocation, securityPolicyRuleEntry, *securityPolicyRuleReply.Uuid)
securityPolicyRuleEntry.Description = util.String("changed by name description")
securityPolicyRuleReply, err = securityPolicyRuleApi.Update(ctx, *securityPolicyRuleLocation, securityPolicyRuleEntry, securityPolicyRuleReply.Name)
if err != nil {
log.Printf("Failed to update security policy rule: %s", err)
return
Expand Down Expand Up @@ -1038,21 +1037,6 @@ func checkService(c *pango.Client, ctx context.Context) {
return
}

readDescription := ""
if serviceReply.Description != nil {
readDescription = *serviceReply.Description
}

keys := make([]string, 0, len(serviceReply.Misc))
xmls := make([]string, 0, len(serviceReply.Misc))
for key := range serviceReply.Misc {
keys = append(keys, key)
data, _ := xml.Marshal(serviceReply.Misc[key])
xmls = append(xmls, string(data))
}
log.Printf("Service '%s=%s, description: %s misc XML: %s, misc keys: %s' read",
serviceReply.Name, *serviceReply.Protocol.Tcp.Port, readDescription, xmls, keys)

// SERVICE - UPDATE 3
serviceReply.Description = util.String("some text changed now")

Expand All @@ -1061,21 +1045,6 @@ func checkService(c *pango.Client, ctx context.Context) {
log.Printf("Failed to update object: %s", err)
return
}

readDescription = ""
if serviceReply.Description != nil {
readDescription = *serviceReply.Description
}

keys = make([]string, 0, len(serviceReply.Misc))
xmls = make([]string, 0, len(serviceReply.Misc))
for key := range serviceReply.Misc {
keys = append(keys, key)
data, _ := xml.Marshal(serviceReply.Misc[key])
xmls = append(xmls, string(data))
}
log.Printf("Service '%s=%s, description: %s misc XML: %s, misc keys: %s' update",
serviceReply.Name, *serviceReply.Protocol.Tcp.Port, readDescription, xmls, keys)
}

func checkNtp(c *pango.Client, ctx context.Context) {
Expand Down
196 changes: 196 additions & 0 deletions assets/pango/tests/marshalling_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package tests

import (
"encoding/xml"
"fmt"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/PaloAltoNetworks/pango/generic"
"github.com/PaloAltoNetworks/pango/objects/application"
"github.com/PaloAltoNetworks/pango/version"
)

var _ = Describe("XML Marshalling and Unmarshalling tests", func() {
version, _ := version.New("11.0.0")
var specifier application.Specifier
var normalizer application.Normalizer

JustBeforeEach(func() {
specifier, normalizer, _ = application.Versioning(version)
})
Context("When unmarshalling XML document with no unknown nodes", func() {
Context("within top-level object", func() {
It("should return an Entry object with empty Misc field", func() {
data := []byte(`<result><entry name="app-1"></entry></result>`)
err := xml.Unmarshal(data, &normalizer)
Expect(err).To(Not(HaveOccurred()))

entries, err := normalizer.Normalize()
Expect(err).To(Not(HaveOccurred()))
Expect(entries).To(HaveLen(1))

Expect(entries[0].Name).To(Equal("app-1"))
Expect(entries[0].Misc).To(HaveLen(0))
})
})
Context("within child object", func() {
It("should return an Entry object with empty Misc field within child", func() {
data := []byte(`<entry name="app-1"><default><ident-by-ip-protocol>test-protocol</ident-by-ip-protocol></default></entry>`)

marshalled := []byte(fmt.Sprintf("<result>%s</result>", string(data)))
err := xml.Unmarshal(marshalled, &normalizer)
Expect(err).To(Not(HaveOccurred()))

entries, err := normalizer.Normalize()
Expect(err).To(Not(HaveOccurred()))
Expect(entries).To(HaveLen(1))

Expect(entries[0].Name).To(Equal("app-1"))
Expect(entries[0].Misc).To(HaveLen(0))

Expect(entries[0].Default.IdentByIpProtocol).To(Not(BeNil()))
Expect(*entries[0].Default.IdentByIpProtocol).To(Equal("test-protocol"))
Expect(entries[0].Default.Misc).To(HaveLen(0))

specified, err := specifier(entries[0])
Expect(err).To(Not(HaveOccurred()))

marshalled, err = xml.Marshal(specified)
Expect(err).To(Not(HaveOccurred()))
Expect(marshalled).To(Equal(data))
})
})
Context("within a list child object", func() {
It("should return an Entry object with empty Misc field within a list child", func() {
data := []byte(`<entry name="app-1"><signature><entry name="signature-1"><order-free>yes</order-free></entry></signature></entry>`)

marshalled := []byte(fmt.Sprintf("<result>%s</result>", string(data)))
err := xml.Unmarshal(marshalled, &normalizer)
Expect(err).To(Not(HaveOccurred()))

entries, err := normalizer.Normalize()
Expect(err).To(Not(HaveOccurred()))
Expect(entries).To(HaveLen(1))

Expect(entries[0].Name).To(Equal("app-1"))
Expect(entries[0].Misc).To(HaveLen(0))

Expect(entries[0].Signature).To(HaveLen(1))
Expect(entries[0].Signature[0].OrderFree).To(Not(BeNil()))
Expect(*entries[0].Signature[0].OrderFree).To(BeTrue())
Expect(entries[0].Signature[0].Misc).To(HaveLen(0))

specified, err := specifier(entries[0])
Expect(err).To(Not(HaveOccurred()))

marshalled, err = xml.Marshal(specified)
Expect(err).To(Not(HaveOccurred()))
Expect(marshalled).To(Equal(data))
})
})
})
Context("When unmarshalling XML document with no unknown nodes", func() {
var expectedXmlNodes []generic.Xml

JustBeforeEach(func() {
fakeTextString := "fake-text"
expectedXmlNodes = []generic.Xml{
{
XMLName: xml.Name{Local: "fake-node"},
Text: []byte("fake-text"),
TrimmedText: &fakeTextString,
},
}
})
Context("within top-level object", func() {
It("should return an Entry object with a non-empty Misc field", func() {
data := []byte(`<result><entry name="address-1"><fake-node>fake-text</fake-node></entry></result>`)
err := xml.Unmarshal(data, &normalizer)
Expect(err).To(Not(HaveOccurred()))

entries, err := normalizer.Normalize()
Expect(err).To(Not(HaveOccurred()))
Expect(entries).To(HaveLen(1))

Expect(entries[0].Name).To(Equal("address-1"))
Expect(entries[0].Misc).To(HaveExactElements(expectedXmlNodes))
})
})
Context("within child object", func() {
It("should return an Entry object with a non-empty Misc field within child", func() {
data := []byte(`<entry name="app-1"><default><ident-by-ip-protocol>test-protocol</ident-by-ip-protocol><fake-node>fake-text</fake-node></default></entry>`)

marshalled := []byte(fmt.Sprintf("<result>%s</result>", string(data)))
err := xml.Unmarshal(marshalled, &normalizer)
Expect(err).To(Not(HaveOccurred()))

entries, err := normalizer.Normalize()
Expect(err).To(Not(HaveOccurred()))
Expect(entries).To(HaveLen(1))

Expect(entries[0].Name).To(Equal("app-1"))
Expect(entries[0].Misc).To(HaveLen(0))

Expect(entries[0].Default.IdentByIpProtocol).To(Not(BeNil()))
Expect(*entries[0].Default.IdentByIpProtocol).To(Equal("test-protocol"))
Expect(entries[0].Default.Misc).To(HaveExactElements(expectedXmlNodes))

specified, err := specifier(entries[0])
Expect(err).To(Not(HaveOccurred()))

marshalled, err = xml.Marshal(specified)
Expect(err).To(Not(HaveOccurred()))
Expect(marshalled).To(Equal(data))
})
})
Context("within a list child object", func() {
It("should return an Entry object with a non-empty Misc field within a list child, one for each element", func() {
data := []byte(`<entry name="app-1"><signature><entry name="signature-1"><order-free>yes</order-free><fake-node>fake-text1</fake-node></entry><entry name="signature-2"><order-free>no</order-free><fake-node>fake-text2</fake-node></entry></signature></entry>`)

marshalled := []byte(fmt.Sprintf("<result>%s</result>", string(data)))
err := xml.Unmarshal(marshalled, &normalizer)
Expect(err).To(Not(HaveOccurred()))

entries, err := normalizer.Normalize()
Expect(err).To(Not(HaveOccurred()))
Expect(entries).To(HaveLen(1))

Expect(entries[0].Name).To(Equal("app-1"))
Expect(entries[0].Misc).To(HaveLen(0))

Expect(entries[0].Signature).To(HaveLen(2))
Expect(entries[0].Signature[0].OrderFree).To(Not(BeNil()))
Expect(*entries[0].Signature[0].OrderFree).To(BeTrue())

fakeTextString := "fake-text1"
expectedXmlNodes = []generic.Xml{
{
XMLName: xml.Name{Local: "fake-node"},
Text: []byte(fakeTextString),
TrimmedText: &fakeTextString,
},
}
Expect(entries[0].Signature[0].Misc).To(HaveExactElements())

fakeTextString = "fake-text2"
expectedXmlNodes = []generic.Xml{
{
XMLName: xml.Name{Local: "fake-node"},
Text: []byte(fakeTextString),
TrimmedText: &fakeTextString,
},
}
Expect(entries[0].Signature[1].Misc).To(HaveExactElements())

specified, err := specifier(entries[0])
Expect(err).To(Not(HaveOccurred()))

marshalled, err = xml.Marshal(specified)
Expect(err).To(Not(HaveOccurred()))
Expect(marshalled).To(Equal(data))
})
})
})
})
18 changes: 18 additions & 0 deletions assets/pango/tests/tests_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package tests

import (
"log/slog"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestMovement(t *testing.T) {
handler := slog.NewTextHandler(GinkgoWriter, &slog.HandlerOptions{
Level: slog.LevelDebug,
})
slog.SetDefault(slog.New(handler))
RegisterFailHandler(Fail)
RunSpecs(t, "Translate Suite")
}
18 changes: 9 additions & 9 deletions assets/pango/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func AsXpath(i interface{}) string {
}

// AsEntryXpath returns the given values as an entry xpath segment.
func AsEntryXpath(vals []string) string {
func AsEntryXpath(vals ...string) string {
if len(vals) == 0 || (len(vals) == 1 && vals[0] == "") {
return "entry"
}
Expand Down Expand Up @@ -160,18 +160,18 @@ func TemplateXpathPrefix(tmpl, ts string) []string {
return []string{
"config",
"devices",
AsEntryXpath([]string{"localhost.localdomain"}),
AsEntryXpath("localhost.localdomain"),
"template",
AsEntryXpath([]string{tmpl}),
AsEntryXpath(tmpl),
}
}

return []string{
"config",
"devices",
AsEntryXpath([]string{"localhost.localdomain"}),
AsEntryXpath("localhost.localdomain"),
"template-stack",
AsEntryXpath([]string{ts}),
AsEntryXpath(ts),
}
}

Expand All @@ -185,9 +185,9 @@ func DeviceGroupXpathPrefix(dg string) []string {
return []string{
"config",
"devices",
AsEntryXpath([]string{"localhost.localdomain"}),
AsEntryXpath("localhost.localdomain"),
"device-group",
AsEntryXpath([]string{dg}),
AsEntryXpath(dg),
}
}

Expand All @@ -202,9 +202,9 @@ func VsysXpathPrefix(vsys string) []string {
return []string{
"config",
"devices",
AsEntryXpath([]string{"localhost.localdomain"}),
AsEntryXpath("localhost.localdomain"),
"vsys",
AsEntryXpath([]string{vsys}),
AsEntryXpath(vsys),
}
}

Expand Down
8 changes: 4 additions & 4 deletions assets/pango/util/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ func BenchmarkAsXpath(b *testing.B) {
p := []string{
"config",
"devices",
AsEntryXpath([]string{"localhost.localdomain"}),
AsEntryXpath("localhost.localdomain"),
"vsys",
AsEntryXpath([]string{"vsys1"}),
AsEntryXpath("vsys1"),
"import",
"network",
}
Expand All @@ -124,7 +124,7 @@ func BenchmarkAsEntryXpathMultiple(b *testing.B) {
b.ResetTimer()

for i := 0; i < b.N; i++ {
_ = AsEntryXpath(v)
_ = AsEntryXpath(v...)
}
}

Expand Down Expand Up @@ -159,7 +159,7 @@ func TestAsEntryXpath(t *testing.T) {

for _, tc := range testCases {
t.Run(tc.r, func(t *testing.T) {
if AsEntryXpath(tc.v) != tc.r {
if AsEntryXpath(tc.v...) != tc.r {
t.Fail()
}
})
Expand Down
Loading