diff --git a/assets/pango/errors/panos.go b/assets/pango/errors/panos.go
index 16a604bc..b8a80ae3 100644
--- a/assets/pango/errors/panos.go
+++ b/assets/pango/errors/panos.go
@@ -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")
@@ -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,
+ }
+}
diff --git a/assets/pango/example/main.go b/assets/pango/example/main.go
index ee9037c0..9d9e19f0 100644
--- a/assets/pango/example/main.go
+++ b/assets/pango/example/main.go
@@ -2,7 +2,6 @@ package main
import (
"context"
- "encoding/xml"
"fmt"
"log"
@@ -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
@@ -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")
@@ -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) {
diff --git a/assets/pango/tests/marshalling_test.go b/assets/pango/tests/marshalling_test.go
new file mode 100644
index 00000000..868fa835
--- /dev/null
+++ b/assets/pango/tests/marshalling_test.go
@@ -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(``)
+ 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(`test-protocol`)
+
+ marshalled := []byte(fmt.Sprintf("%s", 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(`yes`)
+
+ marshalled := []byte(fmt.Sprintf("%s", 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(`fake-text`)
+ 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(`test-protocolfake-text`)
+
+ marshalled := []byte(fmt.Sprintf("%s", 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(`yesfake-text1nofake-text2`)
+
+ marshalled := []byte(fmt.Sprintf("%s", 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))
+ })
+ })
+ })
+})
diff --git a/assets/pango/tests/tests_suite_test.go b/assets/pango/tests/tests_suite_test.go
new file mode 100644
index 00000000..82f8ddbe
--- /dev/null
+++ b/assets/pango/tests/tests_suite_test.go
@@ -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")
+}
diff --git a/assets/pango/util/util.go b/assets/pango/util/util.go
index b7e0b736..b48f5fd5 100644
--- a/assets/pango/util/util.go
+++ b/assets/pango/util/util.go
@@ -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"
}
@@ -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),
}
}
@@ -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),
}
}
@@ -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),
}
}
diff --git a/assets/pango/util/util_test.go b/assets/pango/util/util_test.go
index 08126d0d..736f09b0 100644
--- a/assets/pango/util/util_test.go
+++ b/assets/pango/util/util_test.go
@@ -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",
}
@@ -124,7 +124,7 @@ func BenchmarkAsEntryXpathMultiple(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
- _ = AsEntryXpath(v)
+ _ = AsEntryXpath(v...)
}
}
@@ -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()
}
})
diff --git a/assets/terraform/examples/resources/panos_ethernet_layer3_subinterface/resource.tf b/assets/terraform/examples/resources/panos_ethernet_layer3_subinterface/resource.tf
new file mode 100644
index 00000000..abf80561
--- /dev/null
+++ b/assets/terraform/examples/resources/panos_ethernet_layer3_subinterface/resource.tf
@@ -0,0 +1,325 @@
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "example-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "example1" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+ comment = "Basic subinterface"
+ netflow_profile = "NetflowProfile1"
+ mtu = 1500
+ adjust_tcp_mss = { enable = true, ipv4_mss_adjustment = 1300, ipv6_mss_adjustment = 1300 }
+ arp = [{ name = "192.168.0.1", hw_address = "00:1a:2b:3c:4d:5e" }]
+ bonjour = { enable = true, group_id = 5, ttl_check = true }
+ decrypt_forward = true
+ df_ignore = true
+ ndp_proxy = { enabled = true, address = [{ name = "10.0.0.1", negate = false }] }
+ ip = [{ name = "192.168.1.1", sdwan_gateway = "192.168.1.1" }]
+}
+
+resource "panos_ethernet_layer3_subinterface" "example2" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.2"
+ tag = 2
+ comment = "IPv6 GUA subinterface"
+ ipv6 = {
+ enabled = true
+ inherited = {
+ assign_addr = [
+ {
+ name = "gua_config"
+ type = {
+ gua = {
+ enable_on_interface = true
+ prefix_pool = "my-gua-pool"
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example3" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.3"
+ tag = 3
+ comment = "IPv6 ULA subinterface"
+ ipv6 = {
+ enabled = true
+ inherited = {
+ assign_addr = [
+ {
+ name = "ula_config"
+ type = {
+ ula = {
+ enable_on_interface = true
+ address = "fd00:1234:5678::/48"
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example4" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.4"
+ tag = 4
+ comment = "SDWAN DDNS subinterface"
+ sdwan_link_settings = {
+ enable = true
+ sdwan_interface_profile = "SdwanProfile1"
+ upstream_nat = {
+ enable = true
+ ddns = {}
+ }
+ }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example5" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.5"
+ tag = 5
+ comment = "SDWAN Static IP FQDN subinterface"
+ sdwan_link_settings = {
+ enable = true
+ sdwan_interface_profile = "SdwanProfile1"
+ upstream_nat = {
+ enable = true
+ static_ip = {
+ fqdn = "example.com"
+ }
+ }
+ }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example6" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.6"
+ tag = 6
+ comment = "SDWAN Static IP Address subinterface"
+ sdwan_link_settings = {
+ enable = true
+ sdwan_interface_profile = "SdwanProfile1"
+ upstream_nat = {
+ enable = true
+ static_ip = {
+ ip_address = "203.0.113.1"
+ }
+ }
+ }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example7" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.7"
+ tag = 7
+ comment = "DHCP Client subinterface"
+ dhcp_client = {
+ create_default_route = true
+ default_route_metric = 10
+ enable = true
+ send_hostname = {
+ enable = true
+ hostname = "dhcp-client-hostname"
+ }
+ }
+ interface_management_profile = "dhcp-client-profile"
+ ipv6 = { enabled = false }
+ sdwan_link_settings = { enable = false }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example8" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.8"
+ tag = 8
+ comment = "IPv6 DHCP Client subinterface"
+ ipv6 = {
+ enabled = true
+ dhcp_client = {
+ accept_ra_route = true
+ default_route_metric = 10
+ enable = true
+ neighbor_discovery = {
+ dad_attempts = 1
+ enable_dad = true
+ enable_ndp_monitor = true
+ ns_interval = 1000
+ reachable_time = 30000
+ }
+ preference = "high"
+ prefix_delegation = {
+ enable = {
+ yes = {
+ pfx_pool_name = "prefix-pool-1"
+ prefix_len = 64
+ prefix_len_hint = true
+ }
+ }
+ }
+ v6_options = {
+ duid_type = "duid-type-llt"
+ enable = {
+ yes = {
+ non_temp_addr = true
+ temp_addr = false
+ }
+ }
+ rapid_commit = true
+ support_srvr_reconfig = true
+ }
+ }
+ }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example9" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.9"
+ tag = 9
+ comment = "IPv6 Neighbor Discovery subinterface"
+ ipv6 = {
+ enabled = true
+ neighbor_discovery = {
+ dad_attempts = 1
+ enable_dad = true
+ enable_ndp_monitor = true
+ ns_interval = 1000
+ reachable_time = 30000
+ neighbor = [
+ {
+ name = "2001:DB8::1/128"
+ hw_address = "00:1a:2b:3c:4d:5e"
+ }
+ ]
+ router_advertisement = {
+ enable = true
+ enable_consistency_check = true
+ hop_limit = "64"
+ lifetime = 1800
+ link_mtu = "1500"
+ managed_flag = true
+ max_interval = 600
+ min_interval = 200
+ other_flag = true
+ reachable_time = "0"
+ retransmission_timer = "0"
+ router_preference = "Medium"
+ dns_support = {
+ enable = true
+ server = [
+ {
+ name = "2001:DB8::1/128"
+ lifetime = 1200
+ }
+ ]
+ suffix = [
+ {
+ name = "suffix1"
+ lifetime = 1200
+ }
+ ]
+ }
+ }
+ }
+ }
+}
+
+resource "panos_ethernet_layer3_subinterface" "example10" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.10"
+ tag = 10
+ comment = "PPPoE subinterface"
+ pppoe = {
+ access_concentrator = "ac-1"
+ authentication = "auto"
+ create_default_route = true
+ default_route_metric = 10
+ enable = true
+ passive = {
+ enable = true
+ }
+ password = "pppoe-password"
+ service = "pppoe-service"
+ static_address = {
+ ip = "192.168.2.1"
+ }
+ username = "pppoe-user"
+ }
+ ipv6 = { enabled = false }
+ sdwan_link_settings = { enable = false }
+}
diff --git a/assets/terraform/go.mod b/assets/terraform/go.mod
index 228c2683..0c555e8b 100644
--- a/assets/terraform/go.mod
+++ b/assets/terraform/go.mod
@@ -13,7 +13,6 @@ require (
github.com/hashicorp/terraform-plugin-testing v1.12.0
github.com/onsi/ginkgo/v2 v2.22.2
github.com/onsi/gomega v1.36.2
- golang.org/x/sync v0.13.0
)
require (
@@ -63,6 +62,7 @@ require (
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/net v0.37.0 // indirect
+ golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/tools v0.28.0 // indirect
diff --git a/assets/terraform/internal/manager/config.go b/assets/terraform/internal/manager/config.go
index be7c003d..c3c05a80 100644
--- a/assets/terraform/internal/manager/config.go
+++ b/assets/terraform/internal/manager/config.go
@@ -9,6 +9,7 @@ import (
sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/util"
"github.com/PaloAltoNetworks/pango/version"
+ "github.com/PaloAltoNetworks/pango/xmlapi"
)
type TFConfigObject[E any] interface {
@@ -18,13 +19,14 @@ type TFConfigObject[E any] interface {
type SDKConfigService[C any, L ConfigLocation] interface {
Create(context.Context, L, C) (C, error)
- Update(context.Context, L, C) (C, error)
- Read(context.Context, L, string) (C, error)
+ CreateWithXpath(context.Context, string, C) error
+ UpdateWithXpath(context.Context, string, C) error
+ ReadWithXpath(context.Context, string, string) (C, error)
Delete(context.Context, L, C) error
}
type ConfigLocation interface {
- Xpath(version.Number) ([]string, error)
+ XpathWithComponents(version.Number, ...string) ([]string, error)
}
type ConfigObjectManager[C any, L ConfigLocation, S SDKConfigService[C, L]] struct {
@@ -41,16 +43,41 @@ func NewConfigObjectManager[C any, L ConfigLocation, S SDKConfigService[C, L]](c
}
}
-func (o *ConfigObjectManager[C, L, S]) Create(ctx context.Context, location L, config C) (C, error) {
- return o.service.Create(ctx, location, config)
+func (o *ConfigObjectManager[C, L, S]) Create(ctx context.Context, location L, components []string, config C) (C, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), components...)
+ if err != nil {
+ return *new(C), err
+ }
+
+ err = o.service.CreateWithXpath(ctx, util.AsXpath(xpath[:len(xpath)-1]), config)
+ if err != nil {
+ return *new(C), err
+ }
+
+ return o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
}
-func (o *ConfigObjectManager[C, L, S]) Update(ctx context.Context, location L, config C) (C, error) {
- return o.service.Update(ctx, location, config)
+func (o *ConfigObjectManager[C, L, S]) Update(ctx context.Context, location L, components []string, config C) (C, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), components...)
+ if err != nil {
+ return *new(C), err
+ }
+
+ err = o.service.UpdateWithXpath(ctx, util.AsXpath(xpath), config)
+ if err != nil {
+ return *new(C), err
+ }
+
+ return o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
}
-func (o *ConfigObjectManager[C, L, S]) Read(ctx context.Context, location L) (C, error) {
- obj, err := o.service.Read(ctx, location, "get")
+func (o *ConfigObjectManager[C, L, S]) Read(ctx context.Context, location L, components []string) (C, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), components...)
+ if err != nil {
+ return *new(C), err
+ }
+
+ obj, err := o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
if err != nil && sdkerrors.IsObjectNotFound(err) {
return obj, ErrObjectNotFound
}
@@ -59,5 +86,23 @@ func (o *ConfigObjectManager[C, L, S]) Read(ctx context.Context, location L) (C,
}
func (o *ConfigObjectManager[C, L, S]) Delete(ctx context.Context, location L, config C) error {
- return o.service.Delete(ctx, location, config)
+ deletes := xmlapi.NewChunkedMultiConfig(1, 1)
+
+ xpath, err := location.XpathWithComponents(o.client.Versioning())
+ if err != nil {
+ return err
+ }
+
+ deletes.Add(&xmlapi.Config{
+ Action: "delete",
+ Xpath: util.AsXpath(xpath),
+ Target: o.client.GetTarget(),
+ })
+
+ _, _, _, err = o.client.MultiConfig(ctx, deletes, false, nil)
+ if err != nil {
+ return &Error{err: err, message: "sdk error while deleting"}
+ }
+
+ return nil
}
diff --git a/assets/terraform/internal/manager/entry.go b/assets/terraform/internal/manager/entry.go
index 14427563..8992e8fe 100644
--- a/assets/terraform/internal/manager/entry.go
+++ b/assets/terraform/internal/manager/entry.go
@@ -33,15 +33,14 @@ type EntryObject interface {
}
type EntryLocation interface {
- XpathWithEntryName(version.Number, string) ([]string, error)
+ XpathWithComponents(version.Number, ...string) ([]string, error)
}
type SDKEntryService[E EntryObject, L EntryLocation] interface {
- Create(context.Context, L, E) (E, error)
- List(context.Context, L, string, string, string) ([]E, error)
- Read(context.Context, L, string, string) (E, error)
- Update(context.Context, L, E, string) (E, error)
- Delete(context.Context, L, ...string) error
+ CreateWithXpath(context.Context, string, E) error
+ ReadWithXpath(context.Context, string, string) (E, error)
+ ListWithXpath(context.Context, string, string, string, string) ([]E, error)
+ UpdateWithXpath(context.Context, string, E, string) error
}
type EntryObjectManager[E EntryObject, L EntryLocation, S SDKEntryService[E, L]] struct {
@@ -62,8 +61,13 @@ func NewEntryObjectManager[E EntryObject, L EntryLocation, S SDKEntryService[E,
}
}
-func (o *EntryObjectManager[E, L, S]) ReadMany(ctx context.Context, location L, entries []E) ([]E, error) {
- existing, err := o.service.List(ctx, location, "get", "", "")
+func (o *EntryObjectManager[E, L, S]) ReadMany(ctx context.Context, location L, components []string, entries []E) ([]E, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(""))...)
+ if err != nil {
+ return nil, err
+ }
+
+ existing, err := o.service.ListWithXpath(ctx, util.AsXpath(xpath), "get", "", "")
if err != nil {
if sdkerrors.IsObjectNotFound(err) {
return nil, ErrObjectNotFound
@@ -84,8 +88,13 @@ func (o *EntryObjectManager[E, L, S]) ReadMany(ctx context.Context, location L,
return filtered, nil
}
-func (o *EntryObjectManager[E, L, S]) Read(ctx context.Context, location L, name string) (E, error) {
- object, err := o.service.Read(ctx, location, name, "get")
+func (o *EntryObjectManager[E, L, S]) Read(ctx context.Context, location L, parentComponents []string, name string) (E, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(parentComponents, util.AsEntryXpath(name))...)
+ if err != nil {
+ return *new(E), &Error{err: err, message: "failed to read entry from the server"}
+ }
+
+ object, err := o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
if err != nil {
if sdkerrors.IsObjectNotFound(err) {
return *new(E), ErrObjectNotFound
@@ -96,25 +105,42 @@ func (o *EntryObjectManager[E, L, S]) Read(ctx context.Context, location L, name
return object, nil
}
-func (o *EntryObjectManager[E, T, S]) Create(ctx context.Context, location T, entry E) (E, error) {
- existing, err := o.service.List(ctx, location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
+func (o *EntryObjectManager[E, L, S]) Create(ctx context.Context, location L, parentComponents []string, entry E) (E, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(parentComponents, util.AsEntryXpath(entry.EntryName()))...)
+ if err != nil {
return *new(E), err
}
- for _, elt := range existing {
- if elt.EntryName() == entry.EntryName() {
- return *new(E), ErrConflict
- }
+ _, err = o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
+ if err == nil {
+ return *new(E), &Error{err: ErrConflict, message: fmt.Sprintf("entry '%s' already exists", entry.EntryName())}
}
- obj, err := o.service.Create(ctx, location, entry)
- return obj, err
+ if err != nil && !sdkerrors.IsObjectNotFound(err) {
+ return *new(E), &Error{err: err, message: "failed to read existing entry from the server"}
+ }
+
+ err = o.service.CreateWithXpath(ctx, util.AsXpath(xpath[:len(xpath)-1]), entry)
+ if err != nil {
+ return *new(E), &Error{err: err, message: "failed to create entry on the server"}
+ }
+
+ obj, err := o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
+ if err != nil {
+ return *new(E), &Error{err: err, message: "failed to read created entry from the server"}
+ }
+
+ return obj, nil
}
-func (o *EntryObjectManager[E, L, S]) CreateMany(ctx context.Context, location L, entries []E) ([]E, error) {
+func (o *EntryObjectManager[E, L, S]) CreateMany(ctx context.Context, location L, parentComponents []string, entries []E) ([]E, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(parentComponents, util.AsEntryXpath(""))...)
+ if err != nil {
+ return nil, err
+ }
+
// First, check if none of the entries from the plan already exist on the server
- existing, err := o.service.List(ctx, location, "get", "", "")
+ existing, err := o.service.ListWithXpath(ctx, util.AsXpath(xpath), "get", "", "")
if err != nil && !sdkerrors.IsObjectNotFound(err) {
return nil, &Error{err: err, message: "failed to list existing entries on the server"}
}
@@ -130,7 +156,8 @@ func (o *EntryObjectManager[E, L, S]) CreateMany(ctx context.Context, location L
updates := xmlapi.NewChunkedMultiConfig(len(existing), o.batchSize)
for _, elt := range entries {
- path, err := location.XpathWithEntryName(o.client.Versioning(), elt.EntryName())
+ components := append(parentComponents, util.AsEntryXpath(elt.EntryName()))
+ path, err := location.XpathWithComponents(o.client.Versioning(), components...)
if err != nil {
return nil, &Error{err: err, message: "failed to create xpath for an existing entry"}
}
@@ -154,7 +181,12 @@ func (o *EntryObjectManager[E, L, S]) CreateMany(ctx context.Context, location L
}
}
- existing, err = o.service.List(ctx, location, "get", "", "")
+ xpath, err = location.XpathWithComponents(o.client.Versioning(), append(parentComponents, util.AsEntryXpath(""))...)
+ if err != nil {
+ return nil, err
+ }
+
+ existing, err = o.service.ListWithXpath(ctx, util.AsXpath(xpath), "get", "", "")
if err != nil && !sdkerrors.IsObjectNotFound(err) {
return nil, &Error{err: err, message: "failed to list existing entries on the server"}
}
@@ -170,20 +202,38 @@ func (o *EntryObjectManager[E, L, S]) CreateMany(ctx context.Context, location L
return filtered, nil
}
-func (o *EntryObjectManager[E, T, S]) Delete(ctx context.Context, location T, names []string) error {
- err := o.service.Delete(ctx, location, names...)
- if err != nil {
- if sdkerrors.IsObjectNotFound(err) {
- return ErrObjectNotFound
- } else {
- return &Error{err: err, message: "sdk error while deleting"}
+func (o *EntryObjectManager[E, T, S]) Delete(ctx context.Context, location T, parentComponents []string, names []string) error {
+ deletes := xmlapi.NewChunkedMultiConfig(o.batchSize, len(names))
+
+ for _, elt := range names {
+ components := append(parentComponents, util.AsEntryXpath(elt))
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), components...)
+ if err != nil {
+ return err
}
+
+ deletes.Add(&xmlapi.Config{
+ Action: "delete",
+ Xpath: util.AsXpath(xpath),
+ Target: o.client.GetTarget(),
+ })
+ }
+
+ _, _, _, err := o.client.MultiConfig(ctx, deletes, false, nil)
+ if err != nil {
+ return &Error{err: err, message: "sdk error while deleting"}
}
+
return nil
}
-func (o *EntryObjectManager[E, L, S]) Update(ctx context.Context, location L, entry E, name string) (E, error) {
- updated, err := o.service.Update(ctx, location, entry, name)
+func (o *EntryObjectManager[E, L, S]) Update(ctx context.Context, location L, components []string, entry E, name string) (E, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(name))...)
+ if err != nil {
+ return *new(E), err
+ }
+
+ err = o.service.UpdateWithXpath(ctx, util.AsXpath(xpath), entry, name)
if err != nil {
if sdkerrors.IsObjectNotFound(err) {
return *new(E), ErrObjectNotFound
@@ -192,10 +242,10 @@ func (o *EntryObjectManager[E, L, S]) Update(ctx context.Context, location L, en
}
}
- return updated, nil
+ return o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
}
-func (o *EntryObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L, stateEntries []E, planEntries []E) ([]E, error) {
+func (o *EntryObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L, components []string, stateEntries []E, planEntries []E) ([]E, error) {
stateEntriesByName := o.entriesByName(stateEntries, entryUnknown)
planEntriesByName := o.entriesByName(planEntries, entryUnknown)
renamedEntries := make(map[string]struct{})
@@ -272,7 +322,12 @@ func (o *EntryObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L
}
}
- existing, err := o.service.List(ctx, location, "get", "", "")
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(""))...)
+ if err != nil {
+ return nil, err
+ }
+
+ existing, err := o.service.ListWithXpath(ctx, util.AsXpath(xpath), "get", "", "")
if err != nil && !sdkerrors.IsObjectNotFound(err) {
return nil, &Error{err: err, message: "failed to get a list of existing entries from the server"}
}
@@ -296,7 +351,8 @@ func (o *EntryObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L
return nil, &Error{err: ErrConflict, message: "entry with a matching name already exists"}
}
- path, err := location.XpathWithEntryName(o.client.Versioning(), existingEntryName)
+ components := append(components, util.AsEntryXpath(existingEntryName))
+ path, err := location.XpathWithComponents(o.client.Versioning(), components...)
if err != nil {
return nil, &Error{err: err, message: "failed to create xpath for an existing entry"}
}
@@ -331,7 +387,7 @@ func (o *EntryObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L
}
for _, elt := range processedStateEntriesByName {
- path, err := location.XpathWithEntryName(o.client.Versioning(), elt.Entry.EntryName())
+ path, err := location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(elt.Entry.EntryName()))...)
if err != nil {
return nil, &Error{err: err, message: "failed to create xpath for entry"}
}
@@ -384,7 +440,12 @@ func (o *EntryObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L
}
}
- existing, err = o.service.List(ctx, location, "get", "", "")
+ xpath, err = location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(""))...)
+ if err != nil {
+ return nil, err
+ }
+
+ existing, err = o.service.ListWithXpath(ctx, util.AsXpath(xpath), "get", "", "")
if err != nil && !sdkerrors.IsObjectNotFound(err) {
return nil, fmt.Errorf("Failed to list remote entries: %w", err)
}
diff --git a/assets/terraform/internal/manager/entry_import.go b/assets/terraform/internal/manager/entry_import.go
index e98a23fe..7d5d8a65 100644
--- a/assets/terraform/internal/manager/entry_import.go
+++ b/assets/terraform/internal/manager/entry_import.go
@@ -2,27 +2,35 @@ package manager
import (
"context"
+ "errors"
+ "fmt"
sdkerrors "github.com/PaloAltoNetworks/pango/errors"
+ "github.com/PaloAltoNetworks/pango/util"
+ "github.com/PaloAltoNetworks/pango/xmlapi"
)
type SDKImportableEntryService[E EntryObject, L EntryLocation, IL ImportLocation] interface {
- Create(context.Context, L, []IL, E) (E, error)
- Read(context.Context, L, string, string) (E, error)
+ CreateWithXpath(context.Context, string, E) error
+ ReadWithXpath(context.Context, string, string) (E, error)
List(context.Context, L, string, string, string) ([]E, error)
- Update(context.Context, L, E, string) (E, error)
+ UpdateWithXpath(context.Context, string, E, string) error
Delete(context.Context, L, []IL, ...string) error
+ ImportToLocations(context.Context, L, []IL, string) error
+ UnimportFromLocations(context.Context, L, []IL, []string) error
}
type ImportableEntryObjectManager[E EntryObject, L EntryLocation, IL ImportLocation, IS SDKImportableEntryService[E, L, IL]] struct {
+ batchSize int
service IS
client SDKClient
specifier func(E) (any, error)
matcher func(E, E) bool
}
-func NewImportableEntryObjectManager[E EntryObject, L EntryLocation, IL ImportLocation, IS SDKImportableEntryService[E, L, IL]](client SDKClient, service IS, specifier func(E) (any, error), matcher func(E, E) bool) *ImportableEntryObjectManager[E, L, IL, IS] {
+func NewImportableEntryObjectManager[E EntryObject, L EntryLocation, IL ImportLocation, IS SDKImportableEntryService[E, L, IL]](client SDKClient, service IS, batchSize int, specifier func(E) (any, error), matcher func(E, E) bool) *ImportableEntryObjectManager[E, L, IL, IS] {
return &ImportableEntryObjectManager[E, L, IL, IS]{
+ batchSize: batchSize,
service: service,
client: client,
specifier: specifier,
@@ -34,44 +42,91 @@ func (o *ImportableEntryObjectManager[E, L, IL, IS]) ReadMany(ctx context.Contex
return nil, &Error{err: ErrInternal, message: "called ReadMany on an importable singular resource"}
}
-func (o *ImportableEntryObjectManager[E, L, IL, IS]) Read(ctx context.Context, location L, name string) (E, error) {
- object, err := o.service.Read(ctx, location, name, "get")
+func (o *ImportableEntryObjectManager[E, L, IL, IS]) Read(ctx context.Context, location L, components []string, name string) (E, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(name))...)
if err != nil {
- return *new(E), ErrObjectNotFound
+ return *new(E), err
+ }
+
+ object, err := o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
+ if err != nil {
+ if sdkerrors.IsObjectNotFound(err) {
+ return *new(E), ErrObjectNotFound
+ }
+ return *new(E), &Error{err: err}
}
return object, nil
}
-func (o *ImportableEntryObjectManager[E, L, IL, IS]) Create(ctx context.Context, location L, importLocs []IL, entry E) (E, error) {
- existing, err := o.service.List(ctx, location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
+func (o *ImportableEntryObjectManager[E, L, IL, IS]) Create(ctx context.Context, location L, components []string, entry E) (E, error) {
+ name := entry.EntryName()
+
+ _, err := o.Read(ctx, location, components, name)
+ if err == nil {
+ return *new(E), &Error{err: ErrConflict, message: fmt.Sprintf("entry '%s' already exists", name)}
+ }
+
+ if err != nil && !errors.Is(err, ErrObjectNotFound) {
return *new(E), err
}
- for _, elt := range existing {
- if elt.EntryName() == entry.EntryName() {
- return *new(E), ErrConflict
- }
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(name))...)
+ if err != nil {
+ return *new(E), err
+ }
+
+ err = o.service.CreateWithXpath(ctx, util.AsXpath(xpath[:len(xpath)-1]), entry)
+ if err != nil {
+ return *new(E), err
}
- obj, err := o.service.Create(ctx, location, importLocs, entry)
- return obj, err
+ return o.Read(ctx, location, components, name)
}
-func (o *ImportableEntryObjectManager[E, L, IL, IS]) Update(ctx context.Context, location L, entry E, name string) (E, error) {
- updated, err := o.service.Update(ctx, location, entry, name)
+func (o *ImportableEntryObjectManager[E, L, IL, IS]) Update(ctx context.Context, location L, components []string, entry E, name string) (E, error) {
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), append(components, util.AsEntryXpath(entry.EntryName()))...)
if err != nil {
return *new(E), &Error{err: err, message: "error during Update call"}
}
- return updated, nil
+ err = o.service.UpdateWithXpath(ctx, util.AsXpath(xpath), entry, name)
+ if err != nil {
+ return *new(E), &Error{err: err, message: "error during Update call"}
+ }
+
+ return o.service.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
}
-func (o *ImportableEntryObjectManager[E, L, IL, IS]) Delete(ctx context.Context, location L, importLocations []IL, names []string, exhaustive ExhaustiveType) error {
- err := o.service.Delete(ctx, location, importLocations, names...)
+func (o *ImportableEntryObjectManager[E, L, IL, IS]) Delete(ctx context.Context, location L, importLocations []IL, components []string, names []string) error {
+ deletes := xmlapi.NewChunkedMultiConfig(o.batchSize, len(names))
+
+ for _, elt := range names {
+ components := append(components, util.AsEntryXpath(elt))
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), components...)
+ if err != nil {
+ return err
+ }
+
+ deletes.Add(&xmlapi.Config{
+ Action: "delete",
+ Xpath: util.AsXpath(xpath),
+ Target: o.client.GetTarget(),
+ })
+ }
+
+ _, _, _, err := o.client.MultiConfig(ctx, deletes, false, nil)
if err != nil {
return &Error{err: err, message: "sdk error while deleting"}
}
+
return nil
}
+
+func (o *ImportableEntryObjectManager[E, L, IL, IS]) ImportToLocations(ctx context.Context, location L, importLocs []IL, entry string) error {
+ return o.service.ImportToLocations(ctx, location, importLocs, entry)
+}
+
+func (o *ImportableEntryObjectManager[E, L, IL, IS]) UnimportFromLocations(ctx context.Context, location L, importLocs []IL, entry string) error {
+ return o.service.UnimportFromLocations(ctx, location, importLocs, []string{entry})
+}
diff --git a/assets/terraform/internal/manager/entry_test.go b/assets/terraform/internal/manager/entry_test.go
index 0fd67ca2..f4f27ad4 100644
--- a/assets/terraform/internal/manager/entry_test.go
+++ b/assets/terraform/internal/manager/entry_test.go
@@ -14,8 +14,8 @@ var _ = Expect
var _ = Describe("Entry", func() {
existing := []*MockEntryObject{{Name: "1", Value: "A"}, {Name: "2", Value: "B"}, {Name: "3", Value: "C"}}
var client *MockEntryClient[*MockEntryObject]
- var service manager.SDKEntryService[*MockEntryObject, MockLocation]
- var sdk *manager.EntryObjectManager[*MockEntryObject, MockLocation, manager.SDKEntryService[*MockEntryObject, MockLocation]]
+ var service *MockEntryService[*MockEntryObject, MockLocation]
+ var sdk *manager.EntryObjectManager[*MockEntryObject, MockLocation, *MockEntryService[*MockEntryObject, MockLocation]]
var batchSize int
location := MockLocation{}
@@ -26,13 +26,14 @@ var _ = Describe("Entry", func() {
batchSize = 500
client = NewMockEntryClient(existing)
service = NewMockEntryService[*MockEntryObject, MockLocation](client)
- sdk = manager.NewEntryObjectManager(client, service, batchSize, MockEntrySpecifier, MockEntryMatcher)
+ sdk = manager.NewEntryObjectManager[*MockEntryObject, MockLocation, *MockEntryService[*MockEntryObject, MockLocation]](client, service, batchSize, MockEntrySpecifier, MockEntryMatcher)
})
Context("Read()", func() {
When("reading entry that does not exist", func() {
It("should return nil object and ErrObjectNotFound error", func() {
- object, err := sdk.Read(ctx, location, "4")
+ object, err := sdk.Read(ctx, location, []string{}, "4")
+
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(MatchRegexp("Object not found")))
Expect(object).To(BeNil())
@@ -40,7 +41,7 @@ var _ = Describe("Entry", func() {
})
When("reading entry that exists", func() {
It("should return nil error and the existing entry", func() {
- object, err := sdk.Read(ctx, location, "1")
+ object, err := sdk.Read(ctx, location, []string{}, "1")
Expect(err).ToNot(HaveOccurred())
Expect(object.Name).To(Equal("1"))
})
@@ -51,7 +52,7 @@ var _ = Describe("Entry", func() {
When("no entries are in the state", func() {
It("should return an empty list of entries", func() {
entries := []*MockEntryObject{}
- processed, err := sdk.ReadMany(ctx, location, entries)
+ processed, err := sdk.ReadMany(ctx, location, []string{}, entries)
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(0))
})
@@ -59,7 +60,7 @@ var _ = Describe("Entry", func() {
When("there are entries in the state", func() {
It("should return a list of entries from the server that match state entries", func() {
entries := []*MockEntryObject{{Name: "1"}, {Name: "2"}}
- processed, err := sdk.ReadMany(ctx, location, entries)
+ processed, err := sdk.ReadMany(ctx, location, []string{}, entries)
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(2))
@@ -74,7 +75,7 @@ var _ = Describe("Entry", func() {
Context("when the entry already exists on the server", func() {
It("should return an error back to the caller", func() {
entry := &MockEntryObject{Name: "1", Value: "A"}
- processed, err := sdk.Create(ctx, location, entry)
+ processed, err := sdk.Create(ctx, location, []string{entry.EntryName()}, entry)
Expect(err).To(MatchError(MatchRegexp("already exists")))
Expect(processed).To(BeNil())
@@ -83,7 +84,7 @@ var _ = Describe("Entry", func() {
Context("when there is no conflict between plan and remote state", func() {
It("should return a pointer to the created object", func() {
entry := &MockEntryObject{Name: "4", Value: "D"}
- processed, err := sdk.Create(ctx, location, entry)
+ processed, err := sdk.Create(ctx, location, []string{entry.EntryName()}, entry)
Expect(err).ToNot(HaveOccurred())
Expect(processed).ToNot(BeNil())
Expect(processed.EntryName()).To(Equal(entry.Name))
@@ -98,7 +99,7 @@ var _ = Describe("Entry", func() {
Context("and some entries already exist on the server", func() {
It("should return an error about conflict", func() {
entries := []*MockEntryObject{{Name: "1", Value: "A"}, {Name: "4", Value: "D"}}
- processed, err := sdk.CreateMany(ctx, location, entries)
+ processed, err := sdk.CreateMany(ctx, location, []string{}, entries)
Expect(err).To(MatchError(manager.ErrConflict))
Expect(processed).To(BeNil())
@@ -111,7 +112,7 @@ var _ = Describe("Entry", func() {
Context("and the list of entries is empty", func() {
It("should not make any changes", func() {
entries := []*MockEntryObject{}
- processed, err := sdk.CreateMany(ctx, location, entries)
+ processed, err := sdk.CreateMany(ctx, location, []string{}, entries)
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(BeEmpty())
@@ -124,7 +125,7 @@ var _ = Describe("Entry", func() {
Context("and there are new entries on the list", func() {
It("should add those entries to the server and return only those new entries", func() {
entries := []*MockEntryObject{{Name: "4", Value: "D"}, {Name: "5", Value: "E"}}
- processed, err := sdk.CreateMany(ctx, location, entries)
+ processed, err := sdk.CreateMany(ctx, location, []string{}, entries)
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveExactElements(entries))
@@ -144,7 +145,7 @@ var _ = Describe("Entry", func() {
Context("when entries from the plan are missing from the server", func() {
It("should recreate them, and return back list of all managed entries", func() {
expected := append(existing, &MockEntryObject{Name: "4", Value: "D"})
- processed, err := sdk.UpdateMany(ctx, location, existing, expected)
+ processed, err := sdk.UpdateMany(ctx, location, []string{}, existing, expected)
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveExactElements(expected))
@@ -157,7 +158,7 @@ var _ = Describe("Entry", func() {
It("should properly remove deleted entries from the server and return back updated list", func() {
stateEntries := []*MockEntryObject{{Name: "1", Value: "A"}, {Name: "2", Value: "B"}, {Name: "3", Value: "C"}}
planEntries := []*MockEntryObject{{Name: "1", Value: "A"}, {Name: "3", Value: "C"}}
- processed, err := sdk.UpdateMany(ctx, location, stateEntries, planEntries)
+ processed, err := sdk.UpdateMany(ctx, location, []string{}, stateEntries, planEntries)
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveExactElements(planEntries))
@@ -170,7 +171,7 @@ var _ = Describe("Entry", func() {
Context("when entries from the plan are missing from the server", func() {
It("should not delete anything from the server", func() {
entries := []string{"4"}
- err := sdk.Delete(ctx, location, entries)
+ err := sdk.Delete(ctx, location, []string{}, entries)
Expect(err).ToNot(HaveOccurred())
Expect(client.list()).To(HaveExactElements(existing))
diff --git a/assets/terraform/internal/manager/entry_utils_test.go b/assets/terraform/internal/manager/entry_utils_test.go
index 1ac2c3ed..7d3bd6b2 100644
--- a/assets/terraform/internal/manager/entry_utils_test.go
+++ b/assets/terraform/internal/manager/entry_utils_test.go
@@ -3,8 +3,10 @@ package manager_test
import (
"container/list"
"context"
+ "log/slog"
"net/http"
"net/url"
+ "strings"
sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/version"
@@ -18,24 +20,24 @@ type MockEntryObject struct {
Value string
}
-func (o *MockEntryObject) EntryName() string {
- return o.Name
+func (o *MockEntryObject) EntryUuid() *string {
+ panic("called EntryUuid on MockEntryObject")
}
-func (o *MockEntryObject) SetEntryName(name string) {
- o.Name = name
+func (o *MockEntryObject) SetEntryUuid(value *string) {
+ panic("called SetEntryUuid on MockEntryObject")
}
-func (o *MockEntryObject) EntryUuid() *string {
- panic("mock entry object EntryUuid() called")
+func (o *MockEntryObject) EntryName() string {
+ return o.Name
}
-func (o *MockEntryObject) SetEntryUuid(uuid *string) {
- panic("mock entry object SetEntryUuid() called")
+func (o *MockEntryObject) SetEntryName(name string) {
+ o.Name = name
}
func (o *MockEntryObject) DeepCopy() any {
- return &MockUuidObject{
+ return &MockEntryObject{
Name: o.Name,
Value: o.Value,
}
@@ -43,17 +45,23 @@ func (o *MockEntryObject) DeepCopy() any {
type MockEntryClient[E manager.UuidObject] struct {
Initial *list.List
+ Current *list.List
MultiConfigOpers []MultiConfigOper
}
func NewMockEntryClient[E manager.UuidObject](initial []E) *MockEntryClient[E] {
l := list.New()
+ c := list.New()
+
for _, elt := range initial {
- l.PushBack(elt)
+ entry := interface{}(elt).(*MockEntryObject)
+ l.PushBack(entry)
+ c.PushBack(entry.DeepCopy())
}
return &MockEntryClient[E]{
Initial: l,
+ Current: c,
}
}
@@ -83,14 +91,16 @@ func (o *MockEntryClient[E]) ChunkedMultiConfig(ctx context.Context, updates *xm
}
func (o *MockEntryClient[E]) MultiConfig(ctx context.Context, updates *xmlapi.MultiConfig, arg1 bool, arg2 url.Values) ([]byte, *http.Response, *xmlapi.MultiConfigResponse, error) {
- o.MultiConfigOpers, _ = MultiConfig[E](updates, &o.Initial, multiConfigEntry, 0)
+ o.MultiConfigOpers, _ = MultiConfig[E](updates, &o.Current, multiConfigEntry, 0)
return nil, nil, nil, nil
}
func (o *MockEntryClient[E]) list() []E {
var entries []E
- for e := o.Initial.Front(); e != nil; e = e.Next() {
+ slog.Debug("MockEntryClient list()", "o.Current", o.Current, "o.Current.Front()", o.Current.Front())
+ for e := o.Current.Front(); e != nil; e = e.Next() {
+ slog.Debug("MockEntryClient list()", "entry", e.Value.(E).EntryName())
entries = append(entries, e.Value.(E))
}
@@ -101,28 +111,41 @@ type MockEntryService[E manager.UuidObject, L manager.EntryLocation] struct {
client *MockEntryClient[E]
}
+func (o *MockEntryService[E, L]) CreateWithXpath(ctx context.Context, xpath string, entry E) error {
+ _, err := o.Create(ctx, *new(L), entry)
+ return err
+}
+
func (o *MockEntryService[E, L]) Create(ctx context.Context, location L, entry E) (E, error) {
o.client.Initial.PushBack(entry)
return entry, nil
}
-func (o *MockEntryService[E, L]) Update(ctx context.Context, location L, entry E, name string) (E, error) {
+func (o *MockEntryService[E, L]) UpdateWithXpath(ctx context.Context, xpath string, entry E, name string) error {
for e := o.client.Initial.Front(); e != nil; e = e.Next() {
eltEntry := e.Value.(E)
if entry.EntryName() == eltEntry.EntryName() {
e.Value = entry
- return entry, nil
+ return nil
}
}
- return *new(E), sdkerrors.Panos{Code: 7, Msg: "Object not found"}
+ return sdkerrors.Panos{Code: 7, Msg: "Object not found"}
}
-func (o *MockEntryService[E, L]) List(ctx context.Context, location L, action string, filter string, quote string) ([]E, error) {
+func (o *MockEntryService[E, L]) ListWithXpath(ctx context.Context, xpath string, action string, filter string, quote string) ([]E, error) {
return o.client.list(), nil
}
+func (o *MockEntryService[E, L]) ReadWithXpath(ctx context.Context, xpath string, action string) (E, error) {
+ components := strings.Split(xpath, "/")
+ name := components[len(components)-1]
+ name = strings.TrimPrefix(name, "entry[@name='")
+ name = strings.TrimSuffix(name, "']")
+ return o.Read(ctx, *new(L), name, action)
+}
+
func (o *MockEntryService[E, L]) Read(ctx context.Context, location L, name string, action string) (E, error) {
for e := o.client.Initial.Front(); e != nil; e = e.Next() {
entry := e.Value.(E)
@@ -134,24 +157,6 @@ func (o *MockEntryService[E, L]) Read(ctx context.Context, location L, name stri
return *new(E), sdkerrors.Panos{Code: 7, Msg: "Object not found"}
}
-func (o *MockEntryService[E, L]) Delete(ctx context.Context, location L, names ...string) error {
- namesMap := make(map[string]struct{}, len(names))
- for _, elt := range names {
- namesMap[elt] = struct{}{}
- }
-
- var next *list.Element
- for e := o.client.Initial.Front(); e != nil; e = next {
- next = e.Next()
- entry := e.Value.(E)
- if _, found := namesMap[entry.EntryName()]; found {
- o.client.Initial.Remove(e)
- }
- }
-
- return nil
-}
-
func NewMockEntryService[E manager.UuidObject, L manager.EntryLocation](client *MockEntryClient[E]) *MockEntryService[E, L] {
return &MockEntryService[E, L]{
client: client,
diff --git a/assets/terraform/internal/manager/utils_test.go b/assets/terraform/internal/manager/utils_test.go
index 9cf76065..e8de4f26 100644
--- a/assets/terraform/internal/manager/utils_test.go
+++ b/assets/terraform/internal/manager/utils_test.go
@@ -22,8 +22,8 @@ func (o MockLocation) IsValid() error {
panic("unimplemented")
}
-func (o MockLocation) XpathWithEntryName(version version.Number, name string) ([]string, error) {
- return []string{"some", "location", name}, nil
+func (o MockLocation) XpathWithComponents(version version.Number, components ...string) ([]string, error) {
+ return []string{"some", "location", components[0]}, nil
}
func (o MockLocation) XpathWithUuid(version version.Number, uuid string) ([]string, error) {
@@ -116,6 +116,8 @@ func MultiConfig[E sdkmanager.UuidObject](updates *xmlapi.MultiConfig, existingP
for _, oper := range updates.Operations {
xpathParts := strings.Split(oper.Xpath, "/")
entryName := xpathParts[len(xpathParts)-1]
+ entryName = strings.TrimPrefix(entryName, "entry[@name='")
+ entryName = strings.TrimSuffix(entryName, "']")
op := oper.XMLName.Local
operEntry := MultiConfigOper{
@@ -123,6 +125,8 @@ func MultiConfig[E sdkmanager.UuidObject](updates *xmlapi.MultiConfig, existingP
EntryName: entryName,
}
+ slog.Debug("MultiConfig", "operEntry", operEntry)
+
switch MultiConfigOperType(op) {
case MultiConfigOperSet, MultiConfigOperEdit:
entry := oper.Data.(E)
@@ -147,7 +151,12 @@ func MultiConfig[E sdkmanager.UuidObject](updates *xmlapi.MultiConfig, existingP
idx += 1
}
case MultiConfigOperDelete:
- fixIndices(entriesByName[entryName].Idx)
+ entry, found := entriesByName[entryName]
+ if !found {
+ continue
+ }
+
+ fixIndices(entry.Idx)
delete(entriesByName, entryName)
idx -= 1
case MultiConfigOperMove:
@@ -229,45 +238,33 @@ func MultiConfig[E sdkmanager.UuidObject](updates *xmlapi.MultiConfig, existingP
panic(fmt.Sprintf("UNKNOWN OPERATION: %s", op))
}
- for idx := range entries {
- entries[idx] = nil
- }
+ opers = append(opers, operEntry)
+ }
- for _, elt := range entriesByName {
- if elt.State == entryOk {
- if entries[elt.Idx] != nil {
- var formattedEntries []string
- idx := 1
- for _, elt := range entriesByName {
- formattedEntries = append(
- formattedEntries,
- fmt.Sprintf("%d:{Entry:%s State:%s Idx:%d}", idx, elt.Entry.EntryName(), elt.State, elt.Idx),
- )
- idx += 1
- }
- formattedString := fmt.Sprintf("map[%s]", strings.Join(formattedEntries, " "))
- slog.Debug("Seen elements with duplicated indices", "entries", formattedString)
- panic(fmt.Sprintf("element with idx %d already seen, problem with movement logic", elt.Idx))
- }
- entries[elt.Idx] = &elt
- }
+ for idx := range entries {
+ entries[idx] = nil
+ }
+
+ for _, elt := range entriesByName {
+ if elt.State != entryOk {
+ continue
}
- var orderedEntryNames []string
- transformed := list.New()
- for _, elt := range entries {
- if elt == nil {
- continue
+ if entries[elt.Idx] != nil {
+ var formattedEntries []string
+ idx := 1
+ for _, elt := range entriesByName {
+ formattedEntries = append(
+ formattedEntries,
+ fmt.Sprintf("%d:{Entry:%s State:%s Idx:%d}", idx, elt.Entry.EntryName(), elt.State, elt.Idx),
+ )
+ idx += 1
}
-
- orderedEntryNames = append(orderedEntryNames, elt.Entry.EntryName())
- transformed.PushBack(elt.Entry)
-
+ formattedString := fmt.Sprintf("map[%s]", strings.Join(formattedEntries, " "))
+ slog.Debug("Seen elements with duplicated indices", "entries", formattedString)
+ panic(fmt.Sprintf("element with idx %d already seen, problem with movement logic", elt.Idx))
}
-
- slog.Debug("MultiConfig", "orderedEntryNames", orderedEntryNames)
-
- opers = append(opers, operEntry)
+ entries[elt.Idx] = &elt
}
transformed := list.New()
diff --git a/assets/terraform/internal/manager/uuid.go b/assets/terraform/internal/manager/uuid.go
index eaea56fd..9134455b 100644
--- a/assets/terraform/internal/manager/uuid.go
+++ b/assets/terraform/internal/manager/uuid.go
@@ -30,7 +30,7 @@ type UuidObject interface {
}
type UuidLocation interface {
- XpathWithEntryName(version.Number, string) ([]string, error)
+ XpathWithComponents(version.Number, ...string) ([]string, error)
}
type SDKUuidService[E UuidObject, L UuidLocation] interface {
@@ -219,7 +219,7 @@ func (o *UuidObjectManager[E, L, S]) moveNonExhaustive(ctx context.Context, loca
return nil
}
-func (o *UuidObjectManager[E, L, S]) CreateMany(ctx context.Context, location L, planEntries []E, exhaustive ExhaustiveType, sdkPosition movement.Position) ([]E, error) {
+func (o *UuidObjectManager[E, L, S]) CreateMany(ctx context.Context, location L, parentComponents []string, planEntries []E, exhaustive ExhaustiveType, sdkPosition movement.Position) ([]E, error) {
var diags diag.Diagnostics
planEntriesByName := o.entriesByName(planEntries, entryUnknown)
@@ -237,9 +237,10 @@ func (o *UuidObjectManager[E, L, S]) CreateMany(ctx context.Context, location L,
switch exhaustive {
case Exhaustive:
for _, elt := range existing {
- path, err := location.XpathWithEntryName(o.client.Versioning(), elt.EntryName())
+ components := append(parentComponents, util.AsEntryXpath(elt.EntryName()))
+ path, err := location.XpathWithComponents(o.client.Versioning(), components...)
if err != nil {
- return nil, ErrMarshaling
+ return nil, err
}
updates.Add(&xmlapi.Config{
@@ -257,9 +258,9 @@ func (o *UuidObjectManager[E, L, S]) CreateMany(ctx context.Context, location L,
}
for _, elt := range planEntries {
- path, err := location.XpathWithEntryName(o.client.Versioning(), elt.EntryName())
+ path, err := location.XpathWithComponents(o.client.Versioning(), util.AsEntryXpath(elt.EntryName()))
if err != nil {
- return nil, ErrMarshaling
+ return nil, err
}
xmlEntry, err := o.specifier(elt)
@@ -279,7 +280,7 @@ func (o *UuidObjectManager[E, L, S]) CreateMany(ctx context.Context, location L,
if len(updates.Operations) > 0 {
_, err := o.client.ChunkedMultiConfig(ctx, updates, false, nil)
if err != nil {
- cleanupErr := o.cleanUpIncompleteUpdate(ctx, location, planEntriesByName, exhaustive)
+ cleanupErr := o.cleanUpIncompleteUpdate(ctx, location, parentComponents, planEntriesByName, exhaustive)
return nil, errors.Join(fmt.Errorf("failed to create entries on the server: %w", err), cleanupErr)
}
}
@@ -312,7 +313,7 @@ func (o *UuidObjectManager[E, L, S]) CreateMany(ctx context.Context, location L,
return entries, nil
}
-func (o *UuidObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L, stateEntries []E, planEntries []E, exhaustive ExhaustiveType, position movement.Position) ([]E, error) {
+func (o *UuidObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L, parentComponents []string, stateEntries []E, planEntries []E, exhaustive ExhaustiveType, position movement.Position) ([]E, error) {
stateEntriesByName := o.entriesByName(stateEntries, entryUnknown)
planEntriesByName := o.entriesByName(planEntries, entryUnknown)
if len(planEntriesByName) != len(planEntries) {
@@ -414,7 +415,7 @@ func (o *UuidObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L,
// state to find any required updates.
for _, existingEntry := range existing {
existingEntryName := existingEntry.EntryName()
- path, err := location.XpathWithEntryName(o.client.Versioning(), existingEntryName)
+ path, err := location.XpathWithComponents(o.client.Versioning(), util.AsEntryXpath(existingEntryName))
if err != nil {
return nil, &Error{err: err, message: "failed to create xpath for an existing entry"}
}
@@ -486,7 +487,8 @@ func (o *UuidObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L,
createOps := make([]*xmlapi.Config, len(planEntries))
for _, elt := range processedStateEntries {
- path, err := location.XpathWithEntryName(o.client.Versioning(), elt.Entry.EntryName())
+ components := append(parentComponents, util.AsEntryXpath(elt.Entry.EntryName()))
+ path, err := location.XpathWithComponents(o.client.Versioning(), components...)
if err != nil {
return nil, &Error{err: err, message: "failed to create xpath for an existing entry"}
}
@@ -547,7 +549,7 @@ func (o *UuidObjectManager[E, L, S]) UpdateMany(ctx context.Context, location L,
if len(updates.Operations) > 0 {
if _, err := o.client.ChunkedMultiConfig(ctx, updates, false, nil); err != nil {
- cleanupErr := o.cleanUpIncompleteUpdate(ctx, location, processedStateEntries, exhaustive)
+ cleanupErr := o.cleanUpIncompleteUpdate(ctx, location, parentComponents, processedStateEntries, exhaustive)
return nil, errors.Join(&Error{err: err, message: "failed to execute MultiConfig command"}, cleanupErr)
}
}
@@ -639,29 +641,32 @@ func (o *UuidObjectManager[E, L, S]) ReadMany(ctx context.Context, location L, s
return common, false, nil
}
-func (o *UuidObjectManager[E, L, S]) Delete(ctx context.Context, location L, entryNames []string, exhaustive ExhaustiveType) error {
+func (o *UuidObjectManager[E, L, S]) Delete(ctx context.Context, location L, parentComponents []string, names []string, exhaustive ExhaustiveType) error {
+ deletes := xmlapi.NewChunkedMultiConfig(o.batchSize, len(names))
- var batches [][]string
- for i := 0; i < len(entryNames); i += o.batchSize {
- end := i + o.batchSize
- if end > len(entryNames) {
- end = len(entryNames)
+ for _, elt := range names {
+ components := append(parentComponents, util.AsEntryXpath(elt))
+ xpath, err := location.XpathWithComponents(o.client.Versioning(), components...)
+ if err != nil {
+ return err
}
- batches = append(batches, entryNames[i:end])
+ deletes.Add(&xmlapi.Config{
+ Action: "delete",
+ Xpath: util.AsXpath(xpath),
+ Target: o.client.GetTarget(),
+ })
}
- for _, elt := range batches {
- err := o.service.Delete(ctx, location, elt...)
- if err != nil {
- return &Error{err: err, message: "sdk error while deleting"}
- }
+ _, _, _, err := o.client.MultiConfig(ctx, deletes, false, nil)
+ if err != nil {
+ return &Error{err: err, message: "sdk error while deleting"}
}
return nil
}
-func (o *UuidObjectManager[E, L, S]) cleanUpIncompleteUpdate(ctx context.Context, location L, entries map[string]uuidObjectWithState[E], exhaustive ExhaustiveType) error {
+func (o *UuidObjectManager[E, L, S]) cleanUpIncompleteUpdate(ctx context.Context, location L, parentComponents []string, entries map[string]uuidObjectWithState[E], exhaustive ExhaustiveType) error {
var names []string
for _, elt := range entries {
if elt.State == entryMissing {
@@ -669,5 +674,5 @@ func (o *UuidObjectManager[E, L, S]) cleanUpIncompleteUpdate(ctx context.Context
}
}
- return o.Delete(ctx, location, names, exhaustive)
+ return o.Delete(ctx, location, parentComponents, names, exhaustive)
}
diff --git a/assets/terraform/internal/manager/uuid_test.go b/assets/terraform/internal/manager/uuid_test.go
index 06190575..01653297 100644
--- a/assets/terraform/internal/manager/uuid_test.go
+++ b/assets/terraform/internal/manager/uuid_test.go
@@ -67,7 +67,7 @@ var _ = Describe("Server", func() {
It("CreateMany() should create new entries on the server, and return them with uuid set", func() {
entries := []*MockUuidObject{{Name: "1", Value: "A"}}
- processed, err := manager.CreateMany(ctx, location, entries, sdkmanager.Exhaustive, movement.PositionFirst{})
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.Exhaustive, movement.PositionFirst{})
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(1))
@@ -91,7 +91,7 @@ var _ = Describe("Server", func() {
})
It("should not create any entries and return an error", func() {
- processed, err := manager.CreateMany(ctx, location, entries, mode, position)
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, mode, position)
Expect(err).To(MatchError(sdkmanager.ErrConflict))
Expect(processed).To(BeNil())
@@ -102,7 +102,7 @@ var _ = Describe("Server", func() {
Context("and all entries being created are new to the server", func() {
It("should create those entries in the correct position", func() {
- processed, err := manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(2))
@@ -123,7 +123,7 @@ var _ = Describe("Server", func() {
})
It("should not return any error and overwrite all entries on the server", func() {
- processed, err := manager.CreateMany(ctx, location, entries, mode, position)
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, mode, position)
Expect(err).ToNot(HaveOccurred())
@@ -172,7 +172,7 @@ var _ = Describe("Server", func() {
Expect(processed).To(HaveLen(3))
Expect(processed).NotTo(MatchEntries(entries))
- processed, err = manager.UpdateMany(ctx, location, entries, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
+ processed, err = manager.UpdateMany(ctx, location, []string{}, entries, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(3))
@@ -187,7 +187,7 @@ var _ = Describe("Server", func() {
It("should create new entries on the top of the list", func() {
entries := []*MockUuidObject{{Name: "4", Value: "D"}, {Name: "5", Value: "E"}, {Name: "6", Value: "F"}}
- processed, err := manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(3))
@@ -205,7 +205,7 @@ var _ = Describe("Server", func() {
It("should create new entries on the bottom of the list", func() {
entries := []*MockUuidObject{{Name: "4", Value: "D"}, {Name: "5", Value: "E"}, {Name: "6", Value: "F"}}
- processed, err := manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, movement.PositionLast{})
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, movement.PositionLast{})
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(3))
@@ -223,7 +223,7 @@ var _ = Describe("Server", func() {
It("should create new entries directly after first existing element", func() {
entries := []*MockUuidObject{{Name: "4", Value: "D"}, {Name: "5", Value: "E"}, {Name: "6", Value: "F"}}
- processed, err := manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, movement.PositionAfter{Directly: true, Pivot: initial[0].Name})
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, movement.PositionAfter{Directly: true, Pivot: initial[0].Name})
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(3))
@@ -248,7 +248,7 @@ var _ = Describe("Server", func() {
pivot := initial[2].Name // "3"
position = movement.PositionBefore{Directly: true, Pivot: pivot}
- processed, err := manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+ processed, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, position)
Expect(err).ToNot(HaveOccurred())
Expect(processed).To(HaveLen(3))
@@ -267,7 +267,7 @@ var _ = Describe("Server", func() {
Context("and there is a duplicate entry within a list", func() {
It("should properly raise an error", func() {
entries := []*MockUuidObject{{Name: "4", Value: "D"}, {Name: "4", Value: "D"}}
- _, err := manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
+ _, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, movement.PositionFirst{})
Expect(err).To(MatchError(sdkmanager.ErrPlanConflict))
})
@@ -295,13 +295,13 @@ var _ = Describe("Server", func() {
var position movement.Position
position = movement.PositionFirst{}
- _, err := manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+ _, err := manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, position)
Expect(err).ToNot(HaveOccurred())
entries = []*MockUuidObject{{Name: "99", Value: "ZZ"}}
position = movement.PositionLast{}
- _, err = manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+ _, err = manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, position)
Expect(err).ToNot(HaveOccurred())
current := client.list()
@@ -313,7 +313,7 @@ var _ = Describe("Server", func() {
entries = []*MockUuidObject{{Name: "2", Value: "B"}, {Name: "3", Value: "C"}}
position = movement.PositionAfter{Pivot: "1", Directly: true}
- _, err = manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+ _, err = manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, position)
Expect(err).ToNot(HaveOccurred())
current = client.list()
@@ -330,7 +330,7 @@ var _ = Describe("Server", func() {
entries = []*MockUuidObject{{Name: "4", Value: "D"}, {Name: "5", Value: "E"}}
position = movement.PositionAfter{Pivot: "1", Directly: false}
- _, err = manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+ _, err = manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, position)
Expect(err).ToNot(HaveOccurred())
current = client.list()
@@ -349,7 +349,7 @@ var _ = Describe("Server", func() {
entries = []*MockUuidObject{{Name: "6", Value: "F"}, {Name: "7", Value: "G"}}
position = movement.PositionBefore{Pivot: "99", Directly: true}
- _, err = manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+ _, err = manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, position)
Expect(err).ToNot(HaveOccurred())
current = client.list()
@@ -370,7 +370,7 @@ var _ = Describe("Server", func() {
entries = []*MockUuidObject{{Name: "8", Value: "H"}, {Name: "9", Value: "I"}}
position = movement.PositionBefore{Pivot: "99", Directly: false}
- _, err = manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+ _, err = manager.CreateMany(ctx, location, []string{}, entries, sdkmanager.NonExhaustive, position)
Expect(err).ToNot(HaveOccurred())
current = client.list()
diff --git a/assets/terraform/internal/manager/uuid_utils_test.go b/assets/terraform/internal/manager/uuid_utils_test.go
index 9574d579..4d0b4e01 100644
--- a/assets/terraform/internal/manager/uuid_utils_test.go
+++ b/assets/terraform/internal/manager/uuid_utils_test.go
@@ -212,7 +212,7 @@ func (o *MockUuidService[E, T]) MoveGroup(ctx context.Context, location MockLoca
updates := xmlapi.NewMultiConfig(len(movements))
for _, elt := range movements {
- path, err := location.XpathWithEntryName(o.client.Versioning(), elt.Movable.EntryName())
+ path, err := location.XpathWithComponents(o.client.Versioning(), elt.Movable.EntryName())
if err != nil {
return err
}
diff --git a/assets/terraform/test/resource_address_group_test.go b/assets/terraform/test/resource_address_group_test.go
index 12c83414..b1a26f43 100644
--- a/assets/terraform/test/resource_address_group_test.go
+++ b/assets/terraform/test/resource_address_group_test.go
@@ -1,22 +1,15 @@
package provider_test
import (
- "context"
"fmt"
"testing"
- "golang.org/x/sync/errgroup"
-
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- addressGroup "github.com/PaloAltoNetworks/pango/objects/address/group"
-
"github.com/hashicorp/terraform-plugin-testing/compare"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -31,10 +24,6 @@ func TestAccPanosAddressGroup(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosAddressGroupDestroy(
- fmt.Sprintf("%s-%s", resourceName, nameSuffix),
- fmt.Sprintf("%s-base-%s", resourceName, nameSuffix),
- ),
Steps: []resource.TestStep{
{
Config: makeAddressGroupConfig(resourceName),
@@ -140,37 +129,3 @@ func makeAddressGroupConfig(label string) string {
return fmt.Sprintf(confiTpl, label, label, label)
}
-
-func testAccCheckPanosAddressGroupDestroy(entryNames ...string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := addressGroup.NewService(sdkClient)
- location := addressGroup.NewSharedLocation()
-
- g := new(errgroup.Group)
-
- for _, addrGroupName := range entryNames {
- g.Go(func() error {
- ctx := context.TODO()
-
- reply, err := api.Read(ctx, *location, addrGroupName, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading address group entry %s via sdk: %v", addrGroupName, err)
- }
-
- if reply != nil {
- if reply.EntryName() == addrGroupName {
- return fmt.Errorf("address group object still exists: %s", addrGroupName)
- }
- }
-
- return nil
- })
- }
-
- if err := g.Wait(); err != nil {
- return fmt.Errorf("checking destroy of address objects: %v", err)
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_addresses_test.go b/assets/terraform/test/resource_addresses_test.go
index db32fed7..389a1c92 100644
--- a/assets/terraform/test/resource_addresses_test.go
+++ b/assets/terraform/test/resource_addresses_test.go
@@ -2,33 +2,84 @@ package provider_test
import (
"context"
- "errors"
"fmt"
"strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
+ sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/objects/address"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
+type expectServerAddressObjects struct {
+ Location address.Location
+ Prefix string
+ Addresses []string
+}
+
+func ExpectServerAddressObjects(location address.Location, prefix string, addresses []string) *expectServerAddressObjects {
+ return &expectServerAddressObjects{
+ Location: location,
+ Prefix: prefix,
+ Addresses: addresses,
+ }
+}
+
+func (o *expectServerAddressObjects) CheckState(ctx context.Context, req statecheck.CheckStateRequest, resp *statecheck.CheckStateResponse) {
+ service := address.NewService(sdkClient)
+
+ objects, err := service.List(ctx, o.Location, "get", "", "")
+ if err != nil && !sdkerrors.IsObjectNotFound(err) {
+ resp.Error = err
+ return
+ }
+
+ objectsByName := make(map[string]int)
+ for _, elt := range o.Addresses {
+ objectsByName[fmt.Sprintf("%s-%s", o.Prefix, elt)] = 0
+ }
+
+ for _, elt := range objects {
+ _, found := objectsByName[elt.Name]
+ if !found {
+ objectsByName[elt.Name] = -1
+ } else {
+ objectsByName[elt.Name] = 1
+ }
+ }
+
+ var errors []string
+ for name, state := range objectsByName {
+ switch state {
+ case -1:
+ errors = append(errors, fmt.Sprintf("%s: unexpected", name))
+ case 0:
+ errors = append(errors, fmt.Sprintf("%s: missing", name))
+ }
+ }
+
+ if errors != nil {
+ resp.Error = fmt.Errorf("Unexpected server state: %s", strings.Join(errors, ", "))
+ }
+}
+
func TestAccAddresses(t *testing.T) {
t.Parallel()
nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+ location := address.NewDeviceGroupLocation()
+ location.DeviceGroup.DeviceGroup = prefix
+
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccAddressesDestroy(prefix),
Steps: []resource.TestStep{
{
Config: testAccAddressesResourceTmpl,
@@ -112,6 +163,7 @@ func TestAccAddresses(t *testing.T) {
}),
}),
),
+ ExpectServerAddressObjects(*location, prefix, []string{"ip-netmask", "ip-range", "ip-wildcard", "fqdn"}),
},
},
{
@@ -123,7 +175,7 @@ func TestAccAddresses(t *testing.T) {
"description": config.StringVariable("description"),
"ip_range": config.StringVariable("172.16.0.1-172.16.0.255"),
}),
- fmt.Sprintf("%s-fqdn", prefix): config.ObjectVariable(map[string]config.Variable{
+ fmt.Sprintf("%s-fqdn2", prefix): config.ObjectVariable(map[string]config.Variable{
"fqdn": config.StringVariable("example.com"),
}),
}),
@@ -143,7 +195,7 @@ func TestAccAddresses(t *testing.T) {
"ip_wildcard": knownvalue.Null(),
"fqdn": knownvalue.Null(),
}),
- fmt.Sprintf("%s-fqdn", prefix): knownvalue.ObjectExact(map[string]knownvalue.Check{
+ fmt.Sprintf("%s-fqdn2", prefix): knownvalue.ObjectExact(map[string]knownvalue.Check{
"tags": knownvalue.Null(),
"description": knownvalue.Null(),
"disable_override": knownvalue.Null(),
@@ -154,6 +206,7 @@ func TestAccAddresses(t *testing.T) {
}),
}),
),
+ ExpectServerAddressObjects(*location, prefix, []string{"ip-range", "fqdn2"}),
},
},
{
@@ -161,6 +214,9 @@ func TestAccAddresses(t *testing.T) {
ConfigVariables: map[string]config.Variable{
"prefix": config.StringVariable(prefix),
"addresses": config.MapVariable(map[string]config.Variable{})},
+ ConfigStateChecks: []statecheck.StateCheck{
+ ExpectServerAddressObjects(*location, prefix, []string{}),
+ },
},
{
Config: testAccAddressesResourceTmpl,
@@ -188,8 +244,14 @@ variable "addresses" {
}))
}
+resource "panos_device_group" "example" {
+ location = { panorama = {} }
+
+ name = var.prefix
+}
+
resource "panos_administrative_tag" "tag" {
- location = { shared = {} }
+ location = { device_group = { name = panos_device_group.example.name } }
name = format("%s-tag", var.prefix)
}
@@ -197,7 +259,7 @@ resource "panos_administrative_tag" "tag" {
resource "panos_addresses" "addresses" {
depends_on = [ resource.panos_administrative_tag.tag ]
- location = { shared = {} }
+ location = { device_group = { name = panos_device_group.example.name } }
addresses = { for name, value in var.addresses : name => {
disable_override = value.disable_override,
@@ -210,34 +272,3 @@ resource "panos_addresses" "addresses" {
}}
}
`
-
-func testAccAddressesDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := address.NewService(sdkClient)
- ctx := context.TODO()
-
- location := address.NewSharedLocation()
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("listing interface management entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_admin_role_test.go b/assets/terraform/test/resource_admin_role_test.go
index 900eb7ea..89955139 100644
--- a/assets/terraform/test/resource_admin_role_test.go
+++ b/assets/terraform/test/resource_admin_role_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- "github.com/PaloAltoNetworks/pango/device/adminrole"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -27,7 +20,6 @@ func TestAccAdminRoleDevice(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccAdminRoleDestroy(prefix),
Steps: []resource.TestStep{
{
Config: adminRoleResource1,
@@ -3212,7 +3204,6 @@ func TestAccAdminRoleVsys(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccAdminRoleDestroy(prefix),
Steps: []resource.TestStep{
{
Config: adminRoleResource2,
@@ -6355,39 +6346,3 @@ resource "panos_admin_role" "role" {
}
}
`
-
-func testAccAdminRoleDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := adminrole.NewService(sdkClient)
- ctx := context.TODO()
-
- location := adminrole.NewTemplateLocation()
- location.Template = &adminrole.TemplateLocation{
- Template: fmt.Sprintf("%s-tmpl", prefix),
- PanoramaDevice: "localhost.localdomain",
- }
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("error while listing entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_administrative_tag_test.go b/assets/terraform/test/resource_administrative_tag_test.go
index ba72315b..c381ef5c 100644
--- a/assets/terraform/test/resource_administrative_tag_test.go
+++ b/assets/terraform/test/resource_administrative_tag_test.go
@@ -2,22 +2,16 @@ package provider_test
import (
"bytes"
- "context"
"fmt"
- "strings"
"testing"
"text/template"
- sdkerrors "github.com/PaloAltoNetworks/pango/errors"
- tag "github.com/PaloAltoNetworks/pango/objects/admintag"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -112,23 +106,3 @@ func makeAdministrativeTagConfig(resourceName string) string {
return buf.String()
}
-
-func administrativeTagCheckDestroy(prefix string, location tag.Location) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- service := tag.NewService(sdkClient)
- ctx := context.TODO()
-
- tags, err := service.List(ctx, location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return err
- }
-
- for _, elt := range tags {
- if strings.HasPrefix(elt.Name, prefix) {
- return DanglingObjectsError
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_aggregate_interface_test.go b/assets/terraform/test/resource_aggregate_interface_test.go
index 895460c1..76fcb660 100644
--- a/assets/terraform/test/resource_aggregate_interface_test.go
+++ b/assets/terraform/test/resource_aggregate_interface_test.go
@@ -1,20 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/network/interface/aggregate"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,9 +22,6 @@ func TestAccAggregateInterface_DecryptMirror(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: aggregateInterfaceDecryptMirror1,
@@ -99,9 +90,6 @@ func TestAccAggregateInterface_HA(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: aggregateInterfaceHa1,
@@ -220,9 +208,6 @@ func TestAccAggregateInterface_Layer2(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: aggregateInterfaceLayer21,
@@ -330,9 +315,6 @@ func TestAccAggregateInterface_Layer3_1(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: aggregateInterfaceLayer31,
@@ -513,9 +495,6 @@ func TestAccAggregateInterface_Layer3_2(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: aggregateInterfaceLayer32,
@@ -662,9 +641,6 @@ func TestAccAggregateInterface_Layer3_3(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: aggregateInterfaceLayer33,
@@ -1179,9 +1155,6 @@ func TestAccAggregateInterface_VirtualWire(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: aggregateInterfaceVirtualWire1,
@@ -1248,29 +1221,3 @@ resource "panos_aggregate_interface" "iface" {
}
}
`
-
-func testAccCheckPanosAggregateInterfaceDestroy(prefix string, entry string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := aggregate.NewService(sdkClient)
- ctx := context.TODO()
-
- location := aggregate.NewTemplateLocation()
- location.Template.Template = fmt.Sprintf("%s-tmpl", prefix)
-
- reply, err := api.Read(ctx, *location, entry, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading ethernet entry via sdk: %v", err)
- }
-
- if reply != nil {
- err := fmt.Errorf("terraform didn't delete the server entry properly")
- delErr := api.Delete(ctx, *location, entry)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_application_group_test.go b/assets/terraform/test/resource_application_group_test.go
index 30bb3586..ea49880e 100644
--- a/assets/terraform/test/resource_application_group_test.go
+++ b/assets/terraform/test/resource_application_group_test.go
@@ -2,7 +2,6 @@ package provider_test
import (
"context"
- "errors"
"fmt"
"strings"
"testing"
@@ -10,13 +9,11 @@ import (
sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/objects/application/group"
- // "github.com/hashicorp/terraform-plugin-testing/compare"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -61,7 +58,6 @@ func TestAccPanosApplicationGroup(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosApplicationGroupDestroy(prefix),
Steps: []resource.TestStep{
{
Config: applicationGroupTmpl,
@@ -130,35 +126,3 @@ resource "panos_device_group" "dg" {
name = format("%s-dg1", var.prefix)
}
`
-
-func testAccCheckPanosApplicationGroupDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := group.NewService(sdkClient)
- location := group.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg1", prefix)
-
- ctx := context.TODO()
- existing, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return err
- }
-
- var dangling []string
- for _, elt := range existing {
- if strings.HasPrefix(elt.Name, prefix) {
- dangling = append(dangling, elt.Name)
- }
- }
-
- if len(dangling) > 0 {
- err = fmt.Errorf("Some entries were left after terraform teardown")
- deleteErr := api.Delete(ctx, *location, dangling...)
- if deleteErr != nil {
- err = errors.Join(err, deleteErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_application_test.go b/assets/terraform/test/resource_application_test.go
index 22bff368..bdc5f797 100644
--- a/assets/terraform/test/resource_application_test.go
+++ b/assets/terraform/test/resource_application_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/objects/application"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,7 +21,6 @@ func TestAccApplication(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccApplicationDestroy(prefix),
Steps: []resource.TestStep{
{
Config: testApplicationTmpl,
@@ -316,34 +308,3 @@ resource "panos_application" "app4" {
}
`
-
-func testAccApplicationDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := application.NewService(sdkClient)
- ctx := context.TODO()
-
- location := application.NewSharedLocation()
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("listing interface management entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_custom_url_category_test.go b/assets/terraform/test/resource_custom_url_category_test.go
index b7bc0048..01dcee87 100644
--- a/assets/terraform/test/resource_custom_url_category_test.go
+++ b/assets/terraform/test/resource_custom_url_category_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- category "github.com/PaloAltoNetworks/pango/objects/profiles/customurlcategory"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,7 +21,6 @@ func TestAccCustomUrlCategory(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCustomUrlCategoryDestroy(prefix),
Steps: []resource.TestStep{
{
Config: testAccCustomUrlCategoryResourceTmpl,
@@ -101,34 +93,3 @@ resource "panos_custom_url_category" "category" {
list = var.list
}
`
-
-func testAccCustomUrlCategoryDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := category.NewService(sdkClient)
- ctx := context.TODO()
-
- location := category.NewSharedLocation()
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("listing interface management entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_decryption_policy_test.go b/assets/terraform/test/resource_decryption_policy_test.go
index 14c37430..91ef5de5 100644
--- a/assets/terraform/test/resource_decryption_policy_test.go
+++ b/assets/terraform/test/resource_decryption_policy_test.go
@@ -2,12 +2,10 @@ package provider_test
import (
"context"
- "errors"
"fmt"
"strings"
"testing"
- sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/policies/rules/decryption"
"github.com/hashicorp/terraform-plugin-testing/config"
@@ -16,7 +14,6 @@ import (
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -226,7 +223,6 @@ func TestAccDecryptionPolicyExtended(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: decryptionPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: decryptionPolicyExtendedResource1Tmpl,
@@ -336,7 +332,6 @@ func TestAccPanosDecryptionPolicyOrdering(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: decryptionPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: decryptionPolicyOrderTmpl,
@@ -422,37 +417,3 @@ resource "panos_decryption_policy" "rules" {
]
}
`
-
-func decryptionPolicyCheckDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- service := decryption.NewService(sdkClient)
- ctx := context.TODO()
-
- location := decryption.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg", prefix)
-
- rules, err := service.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return err
- }
-
- var danglingNames []string
- for _, elt := range rules {
- if strings.HasPrefix(elt.Name, prefix) {
- danglingNames = append(danglingNames, elt.Name)
- }
- }
-
- if len(danglingNames) > 0 {
- err := DanglingObjectsError
- delErr := service.Delete(ctx, *location, danglingNames...)
- if delErr != nil {
- err = errors.Join(err, delErr)
- }
-
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_device_group_test.go b/assets/terraform/test/resource_device_group_test.go
index e4817b9a..aaead490 100644
--- a/assets/terraform/test/resource_device_group_test.go
+++ b/assets/terraform/test/resource_device_group_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/panorama/devicegroup"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,7 +21,6 @@ func TestAccDeviceGroup(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccDeviceGroupDestroy(prefix),
Steps: []resource.TestStep{
{
Config: testAccDeviceGroupResourceTmpl,
@@ -95,35 +87,3 @@ resource "panos_device_group" "dg" {
authorization_code = "code"
}
`
-
-func testAccDeviceGroupDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := devicegroup.NewService(sdkClient)
- ctx := context.TODO()
-
- location := devicegroup.NewPanoramaLocation()
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("listing interface management entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_ethernet_interface_test.go b/assets/terraform/test/resource_ethernet_interface_test.go
index d54d4a09..61b4cbc8 100644
--- a/assets/terraform/test/resource_ethernet_interface_test.go
+++ b/assets/terraform/test/resource_ethernet_interface_test.go
@@ -1,19 +1,14 @@
package provider_test
import (
- "context"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/network/interface/ethernet"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,10 +23,6 @@ func TestAccPanosEthernetInterface_Layer3(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosEthernetInterfaceDestroy(
- interfaceName,
- fmt.Sprintf("%s-%s", templateName, nameSuffix),
- ),
Steps: []resource.TestStep{
{
Config: makePanosEthernetInterface_Layer3(resName),
@@ -118,26 +109,3 @@ func makePanosEthernetInterface_Layer3(label string) string {
return fmt.Sprintf(configTpl, label)
}
-
-func testAccCheckPanosEthernetInterfaceDestroy(entryName, templateName string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := ethernet.NewService(sdkClient)
- ctx := context.TODO()
-
- location := ethernet.NewTemplateLocation()
- location.Template.Template = templateName
-
- reply, err := api.Read(ctx, *location, entryName, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading ethernet entry via sdk: %v", err)
- }
-
- if reply != nil {
- if reply.EntryName() == entryName {
- return fmt.Errorf("ethernet object still exists: %s", entryName)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_ethernet_layer3_subinterface_test.go b/assets/terraform/test/resource_ethernet_layer3_subinterface_test.go
new file mode 100644
index 00000000..07b3b329
--- /dev/null
+++ b/assets/terraform/test/resource_ethernet_layer3_subinterface_test.go
@@ -0,0 +1,1297 @@
+package provider_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/config"
+ "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/knownvalue"
+ "github.com/hashicorp/terraform-plugin-testing/plancheck"
+ "github.com/hashicorp/terraform-plugin-testing/statecheck"
+ "github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
+)
+
+func TestAccEthernetLayer3Subinterface_Basic(t *testing.T) {
+ t.Parallel()
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_1,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("name"),
+ knownvalue.StringExact("ethernet1/1.1"),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("tag"),
+ knownvalue.Int64Exact(1),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("parent"),
+ knownvalue.StringExact("ethernet1/1"),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("comment"),
+ knownvalue.StringExact("Test subinterface with all top-level parameters"),
+ ),
+ // statecheck.ExpectKnownValue(
+ // "panos_ethernet_layer3_subinterface.subinterface",
+ // tfjsonpath.New("netflow_profile"),
+ // knownvalue.StringExact("NetflowProfile1"),
+ // ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("mtu"),
+ knownvalue.Int64Exact(1500),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("adjust_tcp_mss"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ "ipv4_mss_adjustment": knownvalue.Int64Exact(100),
+ "ipv6_mss_adjustment": knownvalue.Int64Exact(150),
+ }),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("arp"),
+ knownvalue.ListExact([]knownvalue.Check{
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("192.168.0.1"),
+ "hw_address": knownvalue.StringExact("00:1a:2b:3c:4d:5e"),
+ }),
+ }),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("bonjour"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ "group_id": knownvalue.Int64Exact(5),
+ "ttl_check": knownvalue.Bool(true),
+ }),
+ ),
+ // statecheck.ExpectKnownValue(
+ // "panos_ethernet_layer3_subinterface.subinterface",
+ // tfjsonpath.New("ddns_config"),
+ // knownvalue.ObjectExact(map[string]knownvalue.Check{
+ // "ddns_cert_profile": knownvalue.StringExact("cert-profile-1"),
+ // "ddns_enabled": knownvalue.Bool(true),
+ // "ddns_hostname": knownvalue.StringExact("test-hostname"),
+ // "ddns_ip": knownvalue.ListExact([]knownvalue.Check{knownvalue.StringExact("10.0.0.1")}),
+ // "ddns_ipv6": knownvalue.ListExact([]knownvalue.Check{knownvalue.StringExact("2001:db8::1")}),
+ // "ddns_update_interval": knownvalue.Int64Exact(24),
+ // "ddns_vendor": knownvalue.StringExact("dyndns"),
+ // "ddns_vendor_config": knownvalue.ListExact([]knownvalue.Check{
+ // knownvalue.ObjectExact(map[string]knownvalue.Check{
+ // "name": knownvalue.StringExact("vendor_config_1"),
+ // "value": knownvalue.StringExact("config-value-1"),
+ // }),
+ // }),
+ // }),
+ // ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("df_ignore"),
+ knownvalue.Bool(true),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("interface_management_profile"),
+ knownvalue.StringExact(prefix),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ip"),
+ knownvalue.ListExact([]knownvalue.Check{
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("192.168.1.1"),
+ "sdwan_gateway": knownvalue.StringExact("192.168.1.1"),
+ }),
+ }),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ndp_proxy"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enabled": knownvalue.Bool(true),
+ "address": knownvalue.ListExact([]knownvalue.Check{
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("ndp_proxy_1"),
+ "negate": knownvalue.Bool(false),
+ }),
+ }),
+ }),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ipv6"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enabled": knownvalue.Bool(true),
+ "address": knownvalue.ListExact([]knownvalue.Check{
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("2001:db8:85a3::8a2e:370:7334"),
+ "enable_on_interface": knownvalue.Bool(true),
+ "prefix": knownvalue.ObjectExact(map[string]knownvalue.Check{}),
+ "anycast": knownvalue.ObjectExact(map[string]knownvalue.Check{}),
+ "advertise": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ "valid_lifetime": knownvalue.StringExact("2592000"),
+ "preferred_lifetime": knownvalue.StringExact("604800"),
+ "onlink_flag": knownvalue.Bool(true),
+ "auto_config_flag": knownvalue.Bool(true),
+ }),
+ }),
+ }),
+ "interface_id": knownvalue.StringExact("EUI-64"),
+ "dhcp_client": knownvalue.Null(),
+ "inherited": knownvalue.Null(),
+ "neighbor_discovery": knownvalue.Null(),
+ }),
+ ),
+ // statecheck.ExpectKnownValue(
+ // "panos_ethernet_layer3_subinterface.subinterface",
+ // tfjsonpath.New("sdwan_link_settings"),
+ // knownvalue.ObjectExact(map[string]knownvalue.Check{
+ // "enable": knownvalue.Bool(true),
+ // "sdwan_interface_profile": knownvalue.StringExact("SdwanProfile1"),
+ // "upstream_nat": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ // "enable": knownvalue.Bool(true),
+ // "ddns": knownvalue.ObjectExact(map[string]knownvalue.Check{}),
+ // }),
+ // }),
+ // ),
+ },
+ },
+ {
+ Config: ethernetLayer3Subinterface_1,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectEmptyPlan(),
+ },
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_DHCP_Client(t *testing.T) {
+ t.Parallel()
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_DHCP_Client,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("name"),
+ knownvalue.StringExact("ethernet1/1.1"),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("tag"),
+ knownvalue.Int64Exact(1),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("parent"),
+ knownvalue.StringExact("ethernet1/1"),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("comment"),
+ knownvalue.StringExact("Test subinterface with DHCP client configuration"),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("dhcp_client"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "create_default_route": knownvalue.Bool(true),
+ "default_route_metric": knownvalue.Int64Exact(10),
+ "enable": knownvalue.Bool(true),
+ "send_hostname": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ "hostname": knownvalue.StringExact("dhcp-client-hostname"),
+ }),
+ }),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ipv6").AtMapKey("enabled"),
+ knownvalue.Bool(false),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("sdwan_link_settings").AtMapKey("enable"),
+ knownvalue.Bool(false),
+ ),
+ },
+ },
+ {
+ Config: ethernetLayer3Subinterface_DHCP_Client,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectEmptyPlan(),
+ },
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_PPPoE(t *testing.T) {
+ t.Parallel()
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_PPPoE,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("pppoe"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "access_concentrator": knownvalue.StringExact("ac-1"),
+ "authentication": knownvalue.StringExact("auto"),
+ "create_default_route": knownvalue.Bool(true),
+ "default_route_metric": knownvalue.Int64Exact(10),
+ "enable": knownvalue.Bool(true),
+ "passive": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ }),
+ "password": knownvalue.StringExact("pppoe-password"),
+ "service": knownvalue.StringExact("pppoe-service"),
+ "static_address": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "ip": knownvalue.StringExact("192.168.2.1"),
+ }),
+ "username": knownvalue.StringExact("pppoe-user"),
+ }),
+ ),
+ // Additional checks for other relevant attributes
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ipv6").AtMapKey("enabled"),
+ knownvalue.Bool(false),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("sdwan_link_settings").AtMapKey("enable"),
+ knownvalue.Bool(false),
+ ),
+ },
+ },
+ {
+ Config: ethernetLayer3Subinterface_PPPoE,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigPlanChecks: resource.ConfigPlanChecks{
+ PreApply: []plancheck.PlanCheck{
+ plancheck.ExpectEmptyPlan(),
+ },
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_IPv6_DHCP_Client(t *testing.T) {
+ t.Parallel()
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_IPv6_DHCP_Client,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("name"),
+ knownvalue.StringExact("ethernet1/1.1"),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("tag"),
+ knownvalue.Int64Exact(1),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("comment"),
+ knownvalue.StringExact("Test subinterface with IPv6 DHCP client configuration"),
+ ),
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ipv6"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enabled": knownvalue.Bool(true),
+ "dhcp_client": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "accept_ra_route": knownvalue.Bool(true),
+ "default_route_metric": knownvalue.Int64Exact(10),
+ "enable": knownvalue.Bool(true),
+ "neighbor_discovery": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "dad_attempts": knownvalue.Int64Exact(1),
+ "enable_dad": knownvalue.Bool(true),
+ "enable_ndp_monitor": knownvalue.Bool(true),
+ "ns_interval": knownvalue.Int64Exact(1000),
+ "reachable_time": knownvalue.Int64Exact(30000),
+ "dns_server": knownvalue.Null(),
+ "dns_suffix": knownvalue.Null(),
+ "neighbor": knownvalue.Null(),
+ }),
+ "preference": knownvalue.StringExact("high"),
+ "prefix_delegation": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "yes": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "pfx_pool_name": knownvalue.StringExact("prefix-pool-1"),
+ "prefix_len": knownvalue.Int64Exact(64),
+ "prefix_len_hint": knownvalue.Bool(true),
+ }),
+ "no": knownvalue.Null(),
+ }),
+ }),
+ "v6_options": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "duid_type": knownvalue.StringExact("duid-type-llt"),
+ "enable": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "yes": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "non_temp_addr": knownvalue.Bool(true),
+ "temp_addr": knownvalue.Bool(false),
+ }),
+ "no": knownvalue.Null(),
+ }),
+ "rapid_commit": knownvalue.Bool(true),
+ "support_srvr_reconfig": knownvalue.Bool(true),
+ }),
+ }),
+ "address": knownvalue.Null(),
+ "inherited": knownvalue.Null(),
+ "interface_id": knownvalue.StringExact("EUI-64"),
+ "neighbor_discovery": knownvalue.Null(),
+ }),
+ ),
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_IPv6_Neighbor_Discovery(t *testing.T) {
+ t.Parallel()
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_IPv6_Neighbor_Discovery,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ipv6"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enabled": knownvalue.Bool(true),
+ "neighbor_discovery": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "dad_attempts": knownvalue.Int64Exact(1),
+ "enable_dad": knownvalue.Bool(true),
+ "enable_ndp_monitor": knownvalue.Bool(true),
+ "ns_interval": knownvalue.Int64Exact(1000),
+ "reachable_time": knownvalue.Int64Exact(30000),
+ "router_advertisement": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "dns_support": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ "server": knownvalue.ListExact([]knownvalue.Check{
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("2001:DB8::1/128"),
+ "lifetime": knownvalue.Int64Exact(1200),
+ }),
+ }),
+ "suffix": knownvalue.ListExact([]knownvalue.Check{
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("suffix1"),
+ "lifetime": knownvalue.Int64Exact(1200),
+ }),
+ }),
+ }),
+ "enable": knownvalue.Bool(true),
+ "enable_consistency_check": knownvalue.Bool(true),
+ "hop_limit": knownvalue.StringExact("64"),
+ "lifetime": knownvalue.Int64Exact(1800),
+ "link_mtu": knownvalue.StringExact("1500"),
+ "managed_flag": knownvalue.Bool(false),
+ "max_interval": knownvalue.Int64Exact(600),
+ "min_interval": knownvalue.Int64Exact(200),
+ "other_flag": knownvalue.Bool(false),
+ "reachable_time": knownvalue.StringExact("0"),
+ "retransmission_timer": knownvalue.StringExact("0"),
+ "router_preference": knownvalue.StringExact("Medium"),
+ }),
+ "neighbor": knownvalue.ListExact([]knownvalue.Check{
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("2001:DB8::1/128"),
+ "hw_address": knownvalue.StringExact("00:1a:2b:3c:4d:5e"),
+ }),
+ }),
+ }),
+ "interface_id": knownvalue.StringExact("EUI-64"),
+ "address": knownvalue.Null(),
+ "dhcp_client": knownvalue.Null(),
+ "inherited": knownvalue.Null(),
+ }),
+ ),
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_IPv6_GUA(t *testing.T) {
+ t.Parallel()
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_IPv6_GUA,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ipv6").AtMapKey("inherited").AtMapKey("assign_addr").AtSliceIndex(0),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("gua_config"),
+ "type": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "gua": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable_on_interface": knownvalue.Bool(true),
+ "advertise": knownvalue.Null(),
+ "prefix_pool": knownvalue.Null(),
+ "pool_type": knownvalue.Null(),
+ }),
+ "ula": knownvalue.Null(),
+ }),
+ }),
+ ),
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_IPv6_ULA(t *testing.T) {
+ t.Parallel()
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_IPv6_ULA,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("ipv6").AtMapKey("inherited").AtMapKey("assign_addr").AtSliceIndex(0),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "name": knownvalue.StringExact("ula_config"),
+ "type": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "ula": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable_on_interface": knownvalue.Bool(true),
+ "address": knownvalue.StringExact("fd00:1234:5678::/48"),
+ "advertise": knownvalue.Null(),
+ "anycast": knownvalue.Null(),
+ "prefix": knownvalue.Null(),
+ }),
+ "gua": knownvalue.Null(),
+ }),
+ }),
+ ),
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_SDWAN_DDNS(t *testing.T) {
+ t.Parallel()
+ t.Skip("Missing resource implementation")
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_SDWAN_DDNS,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("sdwan_link_settings"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ "upstream_nat": knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "enable": knownvalue.Bool(true),
+ "ddns": knownvalue.ObjectExact(map[string]knownvalue.Check{}),
+ "static_ip": knownvalue.Null(),
+ }),
+ }),
+ ),
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_SDWAN_StaticIP_FQDN(t *testing.T) {
+ t.Parallel()
+ t.Skip("Missing resource implementation")
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_SDWAN_StaticIP_FQDN,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("sdwan_link_settings").AtMapKey("upstream_nat").AtMapKey("static_ip"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "fqdn": knownvalue.StringExact("example.com"),
+ "ip_address": knownvalue.Null(),
+ }),
+ ),
+ },
+ },
+ },
+ })
+}
+
+func TestAccEthernetLayer3Subinterface_SDWAN_StaticIP_IPAddress(t *testing.T) {
+ t.Parallel()
+ t.Skip("Missing resource implementation")
+
+ nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum)
+ prefix := fmt.Sprintf("test-acc-%s", nameSuffix)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: ethernetLayer3Subinterface_SDWAN_StaticIP_IPAddress,
+ ConfigVariables: map[string]config.Variable{
+ "prefix": config.StringVariable(prefix),
+ },
+ ConfigStateChecks: []statecheck.StateCheck{
+ statecheck.ExpectKnownValue(
+ "panos_ethernet_layer3_subinterface.subinterface",
+ tfjsonpath.New("sdwan_link_settings").AtMapKey("upstream_nat").AtMapKey("static_ip"),
+ knownvalue.ObjectExact(map[string]knownvalue.Check{
+ "ip_address": knownvalue.StringExact("203.0.113.1"),
+ "fqdn": knownvalue.Null(),
+ }),
+ ),
+ },
+ },
+ },
+ })
+}
+
+const ethernetLayer3Subinterface_1 = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_interface_management_profile" "profile" {
+ location = { template = { name = panos_template.example.name } }
+
+ name = var.prefix
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+ comment = "Test subinterface with all top-level parameters"
+ #netflow_profile = "NetflowProfile1"
+ mtu = 1500
+
+ adjust_tcp_mss = {
+ enable = true
+ ipv4_mss_adjustment = 100
+ ipv6_mss_adjustment = 150
+ }
+
+ arp = [
+ {
+ name = "192.168.0.1"
+ hw_address = "00:1a:2b:3c:4d:5e"
+ }
+ ]
+
+ bonjour = {
+ enable = true
+ group_id = 5
+ ttl_check = true
+ }
+
+ #ddns_config = {
+ # ddns_cert_profile = "cert-profile-1"
+ # ddns_enabled = true
+ # ddns_hostname = "test-hostname"
+ # ddns_ip = ["10.0.0.1"]
+ # ddns_ipv6 = ["2001:db8::1"]
+ # ddns_update_interval = 24
+ # ddns_vendor = "dyndns"
+ # ddns_vendor_config = [
+ # {
+ # name = "vendor_config_1"
+ # value = "config-value-1"
+ # }
+ # ]
+ #}
+
+ #decrypt_forward = true
+
+ df_ignore = true
+
+ interface_management_profile = panos_interface_management_profile.profile.name
+
+ ip = [
+ {
+ name = "192.168.1.1"
+ sdwan_gateway = "192.168.1.1"
+ }
+ ]
+
+ ndp_proxy = {
+ enabled = true
+ address = [
+ {
+ name = "ndp_proxy_1"
+ negate = false
+ }
+ ]
+ }
+
+ ipv6 = {
+ enabled = true
+ address = [
+ {
+ name = "2001:db8:85a3::8a2e:370:7334"
+ enable_on_interface = true
+ prefix = {}
+ anycast = {}
+ advertise = {
+ enable = true
+ valid_lifetime = "2592000"
+ preferred_lifetime = "604800"
+ onlink_flag = true
+ auto_config_flag = true
+ }
+ }
+ ]
+
+ interface_id = "EUI-64"
+ }
+
+ #sdwan_link_settings = {
+ # enable = true
+ # sdwan_interface_profile = "SdwanProfile1"
+ # upstream_nat = {
+ # enable = true
+ # ddns = {}
+ # }
+ #}
+}
+`
+
+const ethernetLayer3Subinterface_PPPoE = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+ comment = "Test subinterface with PPPoE configuration"
+ mtu = 1500
+
+ pppoe = {
+ access_concentrator = "ac-1"
+ authentication = "auto"
+ create_default_route = true
+ default_route_metric = 10
+ enable = true
+ passive = {
+ enable = true
+ }
+ password = "pppoe-password"
+ service = "pppoe-service"
+ static_address = {
+ ip = "192.168.2.1"
+ }
+ username = "pppoe-user"
+ }
+
+ // Disable other configurations to focus on PPPoE
+ ipv6 = {
+ enabled = false
+ }
+
+ sdwan_link_settings = {
+ enable = false
+ }
+}
+`
+
+const ethernetLayer3Subinterface_DHCP_Client = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+ comment = "Test subinterface with DHCP client configuration"
+
+ dhcp_client = {
+ create_default_route = true
+ default_route_metric = 10
+ enable = true
+ send_hostname = {
+ enable = true
+ hostname = "dhcp-client-hostname"
+ }
+ }
+
+ // Explicitly disable IPv6 and SDWAN to focus on DHCP client
+ ipv6 = {
+ enabled = false
+ }
+
+ sdwan_link_settings = {
+ enable = false
+ }
+}
+`
+
+const ethernetLayer3Subinterface_IPv6_GUA = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+
+ ipv6 = {
+ inherited = {
+ assign_addr = [{
+ name = "gua_config"
+ type = {
+ gua = {
+ enable_on_interface = true
+ #prefix_pool = "my-gua-pool"
+ }
+ }
+ }]
+ }
+ }
+}
+`
+
+const ethernetLayer3Subinterface_IPv6_DHCP_Client = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+ comment = "Test subinterface with IPv6 DHCP client configuration"
+
+ ipv6 = {
+ enabled = true
+ dhcp_client = {
+ accept_ra_route = true
+ default_route_metric = 10
+ enable = true
+ neighbor_discovery = {
+ dad_attempts = 1
+ enable_dad = true
+ enable_ndp_monitor = true
+ ns_interval = 1000
+ reachable_time = 30000
+ }
+ preference = "high"
+ prefix_delegation = {
+ enable = {
+ yes = {
+ pfx_pool_name = "prefix-pool-1"
+ prefix_len = 64
+ prefix_len_hint = true
+ }
+ }
+ }
+ v6_options = {
+ duid_type = "duid-type-llt"
+ enable = {
+ yes = {
+ non_temp_addr = true
+ temp_addr = false
+ }
+ }
+ rapid_commit = true
+ support_srvr_reconfig = true
+ }
+ }
+ }
+}
+`
+
+const ethernetLayer3Subinterface_IPv6_Neighbor_Discovery = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+ comment = "Test subinterface with IPv6 Neighbor Discovery configuration"
+ mtu = 1500
+
+ ipv6 = {
+ enabled = true
+ neighbor_discovery = {
+ dad_attempts = 1
+ enable_dad = true
+ enable_ndp_monitor = true
+ neighbor = [{
+ name = "2001:DB8::1/128"
+ hw_address = "00:1a:2b:3c:4d:5e"
+ }]
+ ns_interval = 1000
+ reachable_time = 30000
+ router_advertisement = {
+ dns_support = {
+ enable = true
+ server = [
+ {
+ name = "2001:DB8::1/128"
+ lifetime = 1200
+ }
+ ]
+ suffix = [
+ {
+ name = "suffix1"
+ lifetime = 1200
+ }
+ ]
+ }
+ enable = true
+ enable_consistency_check = true
+ hop_limit = "64"
+ lifetime = 1800
+ link_mtu = "1500"
+ managed_flag = false
+ max_interval = 600
+ min_interval = 200
+ other_flag = false
+ reachable_time = "0"
+ retransmission_timer = "0"
+ router_preference = "Medium"
+ }
+ }
+ }
+}
+`
+
+const ethernetLayer3Subinterface_IPv6_ULA = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+
+ ipv6 = {
+ inherited = {
+ assign_addr = [
+ {
+ name = "ula_config"
+ type = {
+ ula = {
+ enable_on_interface = true
+ address = "fd00:1234:5678::/48"
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+`
+
+const ethernetLayer3Subinterface_SDWAN_DDNS = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+
+ sdwan_link_settings = {
+ enable = true
+ upstream_nat = {
+ enable = true
+ ddns = {}
+ }
+ }
+}
+`
+
+const ethernetLayer3Subinterface_SDWAN_StaticIP_FQDN = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+
+ sdwan_link_settings = {
+ enable = true
+ upstream_nat = {
+ enable = true
+ static_ip = {
+ fqdn = "example.com"
+ }
+ }
+ }
+}
+`
+
+const ethernetLayer3Subinterface_SDWAN_StaticIP_IPAddress = `
+variable "prefix" { type = string }
+
+resource "panos_template" "example" {
+ location = { panorama = {} }
+ name = "${var.prefix}-tmpl"
+}
+
+resource "panos_ethernet_interface" "parent" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ name = "ethernet1/1"
+ layer3 = {}
+}
+
+resource "panos_ethernet_layer3_subinterface" "subinterface" {
+ location = {
+ template = {
+ vsys = "vsys1"
+ name = panos_template.example.name
+ }
+ }
+
+ parent = panos_ethernet_interface.parent.name
+ name = "ethernet1/1.1"
+ tag = 1
+
+ sdwan_link_settings = {
+ enable = true
+ upstream_nat = {
+ enable = true
+ static_ip = {
+ ip_address = "203.0.113.1"
+ }
+ }
+ }
+}
+`
diff --git a/assets/terraform/test/resource_external_dynamic_list_test.go b/assets/terraform/test/resource_external_dynamic_list_test.go
index 6fa52e36..3eb70c22 100644
--- a/assets/terraform/test/resource_external_dynamic_list_test.go
+++ b/assets/terraform/test/resource_external_dynamic_list_test.go
@@ -1,19 +1,14 @@
package provider_test
import (
- "context"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/objects/extdynlist"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -25,7 +20,6 @@ func TestAccPanosExternalDynamicList_1(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccExternalDynamicListCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: externalDynamicList1Tmpl,
@@ -89,7 +83,6 @@ func TestAccPanosExternalDynamicList_2(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccExternalDynamicListCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: externalDynamicList2Tmpl,
@@ -150,7 +143,6 @@ func TestAccPanosExternalDynamicList_3(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccExternalDynamicListCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: externalDynamicList3Tmpl,
@@ -211,7 +203,6 @@ func TestAccPanosExternalDynamicList_4(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccExternalDynamicListCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: externalDynamicList4Tmpl,
@@ -275,7 +266,6 @@ func TestAccPanosExternalDynamicList_5(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccExternalDynamicListCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: externalDynamicList5Tmpl,
@@ -324,7 +314,6 @@ func TestAccPanosExternalDynamicList_6(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccExternalDynamicListCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: externalDynamicList6Tmpl,
@@ -373,7 +362,6 @@ func TestAccPanosExternalDynamicList_7(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccExternalDynamicListCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: externalDynamicList7Tmpl,
@@ -653,29 +641,3 @@ resource "panos_external_dynamic_list" "list" {
}
}
`
-
-func testAccExternalDynamicListCheckDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := extdynlist.NewService(sdkClient)
- location := extdynlist.NewDeviceGroupLocation()
-
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg", prefix)
-
- ctx := context.TODO()
-
- entry := fmt.Sprintf("%s-list", prefix)
-
- reply, err := api.Read(ctx, *location, entry, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading external dynamic list entry %s via sdk: %w", entry, err)
- }
-
- if reply != nil {
- if reply.EntryName() == entry {
- return fmt.Errorf("external dynamic list object still exists: %s", entry)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_ike_crypto_profile_test.go b/assets/terraform/test/resource_ike_crypto_profile_test.go
index adf4c9c7..9ea82933 100644
--- a/assets/terraform/test/resource_ike_crypto_profile_test.go
+++ b/assets/terraform/test/resource_ike_crypto_profile_test.go
@@ -1,20 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/objects/profiles/ikecrypto"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -27,7 +21,6 @@ func TestAccIkeCryptoProfile_1(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccIkeCryptoProfileDestroy(prefix),
Steps: []resource.TestStep{
{
Config: ikeCryptoProfile1,
@@ -172,30 +165,3 @@ resource "panos_ike_crypto_profile" "profile4" {
}
}
`
-
-func testAccIkeCryptoProfileDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- entry := fmt.Sprintf("%s-profile", prefix)
- api := ikecrypto.NewService(sdkClient)
- ctx := context.TODO()
-
- location := ikecrypto.NewTemplateLocation()
- location.Template.Template = fmt.Sprintf("%s-tmpl", prefix)
-
- reply, err := api.Read(ctx, *location, entry, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading ethernet entry via sdk: %v", err)
- }
-
- if reply != nil {
- err := fmt.Errorf("terraform didn't delete the server entry properly")
- delErr := api.Delete(ctx, *location, entry)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_interface_management_profile_test.go b/assets/terraform/test/resource_interface_management_profile_test.go
index 4341a251..6b2df5f2 100644
--- a/assets/terraform/test/resource_interface_management_profile_test.go
+++ b/assets/terraform/test/resource_interface_management_profile_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/network/profiles/interface_management"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -35,7 +28,6 @@ func TestAccInterfaceManagementProfile(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccInterfaceManagementProfileDestroy(prefix, templateName),
Steps: []resource.TestStep{
{
Config: interfaceManagementProfileResourceTmpl,
@@ -166,39 +158,3 @@ resource "panos_interface_management_profile" "profile" {
permitted_ips = var.permitted_ips
}
`
-
-func testAccInterfaceManagementProfileDestroy(prefix string, template string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := interface_management.NewService(sdkClient)
- ctx := context.TODO()
-
- location := interface_management.NewTemplateLocation()
- location.Template = &interface_management.TemplateLocation{
- Template: template,
- NgfwDevice: "localhost.localdomain",
- PanoramaDevice: "localhost.localdomain",
- }
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("listing interface management entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_ipsec_crypto_profile_test.go b/assets/terraform/test/resource_ipsec_crypto_profile_test.go
index 07611910..5f381da5 100644
--- a/assets/terraform/test/resource_ipsec_crypto_profile_test.go
+++ b/assets/terraform/test/resource_ipsec_crypto_profile_test.go
@@ -1,20 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/objects/profiles/ipseccrypto"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -27,7 +21,6 @@ func TestAccIpsecCryptoProfile_1(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccIpsecCryptoProfileDestroy(prefix),
Steps: []resource.TestStep{
{
Config: ipsecCryptoProfile1,
@@ -227,30 +220,3 @@ resource "panos_ipsec_crypto_profile" "profile4" {
}
}
`
-
-func testAccIpsecCryptoProfileDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- entry := fmt.Sprintf("%s-profile", prefix)
- api := ipseccrypto.NewService(sdkClient)
- ctx := context.TODO()
-
- location := ipseccrypto.NewTemplateLocation()
- location.Template.Template = fmt.Sprintf("%s-tmpl", prefix)
-
- reply, err := api.Read(ctx, *location, entry, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading ethernet entry via sdk: %v", err)
- }
-
- if reply != nil {
- err := fmt.Errorf("terraform didn't delete the server entry properly")
- delErr := api.Delete(ctx, *location, entry)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_log_forwarding_test.go b/assets/terraform/test/resource_log_forwarding_test.go
index c95b22ae..ced4065d 100644
--- a/assets/terraform/test/resource_log_forwarding_test.go
+++ b/assets/terraform/test/resource_log_forwarding_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/objects/profiles/logforwarding"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -27,7 +20,6 @@ func TestAccLogForwarding(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccLogForwardingDestroy(prefix),
Steps: []resource.TestStep{
{
Config: logForwardingResource1,
@@ -336,39 +328,3 @@ resource "panos_log_forwarding_profile" "profile" {
}]
}
`
-
-func testAccLogForwardingDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := logforwarding.NewService(sdkClient)
- ctx := context.TODO()
-
- location := logforwarding.NewDeviceGroupLocation()
- location.DeviceGroup = &logforwarding.DeviceGroupLocation{
- DeviceGroup: fmt.Sprintf("%s-dg", prefix),
- PanoramaDevice: "localhost.localdomain",
- }
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("error while listing entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_loopback_interface_test.go b/assets/terraform/test/resource_loopback_interface_test.go
index fa5e22ef..5dc73e0f 100644
--- a/assets/terraform/test/resource_loopback_interface_test.go
+++ b/assets/terraform/test/resource_loopback_interface_test.go
@@ -1,20 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/network/interface/loopback"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,9 +22,6 @@ func TestAccLoopbackInterface(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosLoopbackInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: loopbackInterfaceResource1,
@@ -143,29 +134,3 @@ resource "panos_loopback_interface" "iface" {
}
}
`
-
-func testAccCheckPanosLoopbackInterfaceDestroy(prefix string, entry string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := loopback.NewService(sdkClient)
- ctx := context.TODO()
-
- location := loopback.NewTemplateLocation()
- location.Template.Template = fmt.Sprintf("%s-tmpl", prefix)
-
- reply, err := api.Read(ctx, *location, entry, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading ethernet entry via sdk: %v", err)
- }
-
- if reply != nil {
- err := fmt.Errorf("terraform didn't delete the server entry properly")
- delErr := api.Delete(ctx, *location, entry)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_nat_policy_test.go b/assets/terraform/test/resource_nat_policy_test.go
index b9e860b5..43c11add 100644
--- a/assets/terraform/test/resource_nat_policy_test.go
+++ b/assets/terraform/test/resource_nat_policy_test.go
@@ -9,7 +9,6 @@ import (
"testing"
"text/template"
- sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/policies/rules/nat"
"github.com/hashicorp/terraform-plugin-testing/config"
@@ -18,7 +17,6 @@ import (
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -353,7 +351,6 @@ func TestAccNatPolicyExtended(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: natPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: natPolicyExtendedResource1Tmpl,
@@ -448,7 +445,6 @@ func TestAccNatPolicyExtended(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: natPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: natPolicyExtendedResource2Tmpl,
@@ -531,7 +527,6 @@ func TestAccNatPolicyExtended(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: natPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: natPolicyExtendedResource3Tmpl,
@@ -578,7 +573,6 @@ func TestAccNatPolicyExtended(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: natPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: natPolicyExtendedResource4Tmpl,
@@ -679,10 +673,8 @@ func TestAccPanosNatPolicyOrdering(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
natPolicyPreCheck(prefix, sdkLocation)
-
},
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: natPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: makeNatPolicyConfig(prefix),
@@ -851,84 +843,5 @@ func natPolicyPreCheck(prefix string, location nat.Location) {
if err != nil {
panic(fmt.Sprintf("natPolicyPreCheck failed: %s", err))
}
-
}
}
-
-func natPolicyCheckDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- service := nat.NewService(sdkClient)
- ctx := context.TODO()
-
- location := nat.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg", prefix)
-
- rules, err := service.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return err
- }
-
- var danglingNames []string
- for _, elt := range rules {
- if strings.HasPrefix(elt.Name, prefix) {
- danglingNames = append(danglingNames, elt.Name)
- }
- }
-
- if len(danglingNames) > 0 {
- err := DanglingObjectsError
- delErr := service.Delete(ctx, *location, danglingNames...)
- if delErr != nil {
- err = errors.Join(err, delErr)
- }
-
- return err
- }
-
- return nil
- }
-}
-
-func init() {
- resource.AddTestSweepers("pango_nat_policy", &resource.Sweeper{
- Name: "pango_nat_policy",
- F: func(typ string) error {
- service := nat.NewService(sdkClient)
-
- var deviceTyp deviceType
- switch typ {
- case "panorama":
- deviceTyp = devicePanorama
- case "firewall":
- deviceTyp = deviceFirewall
- default:
- panic("invalid device type")
- }
-
- for _, rulebase := range []string{"pre-rulebase", "post-rulebase"} {
- location, _ := natPolicyLocationByDeviceType(deviceTyp, rulebase)
- ctx := context.TODO()
- objects, err := service.List(ctx, location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return fmt.Errorf("Failed to list NAT rules during sweep: %w", err)
- }
-
- var names []string
- for _, elt := range objects {
- if strings.HasPrefix(elt.Name, "test-acc") {
- names = append(names, elt.Name)
- }
- }
-
- if len(names) > 0 {
- err = service.Delete(ctx, location, names...)
- if err != nil {
- return fmt.Errorf("Failed to delete NAT rules during sweep: %w", err)
- }
- }
- }
-
- return nil
- },
- })
-}
diff --git a/assets/terraform/test/resource_panorama_template_test.go b/assets/terraform/test/resource_panorama_template_test.go
index 635cd3f6..7b4b9eed 100644
--- a/assets/terraform/test/resource_panorama_template_test.go
+++ b/assets/terraform/test/resource_panorama_template_test.go
@@ -1,19 +1,14 @@
package provider_test
import (
- "context"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/panorama/template"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -27,7 +22,6 @@ func TestAccPanosTemplate_RequiredInputs(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanoramaTemplateDestroy(templateName),
Steps: []resource.TestStep{
{
Config: makePanosTemplateConfig(resourceName),
@@ -62,24 +56,3 @@ func makePanosTemplateConfig(label string) string {
`
return fmt.Sprintf(configTpl, label)
}
-
-func testAccCheckPanoramaTemplateDestroy(name string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := template.NewService(sdkClient)
- location := template.NewPanoramaLocation()
- ctx := context.TODO()
-
- reply, err := api.Read(ctx, *location, name, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading template entry via sdk: %v", err)
- }
-
- if reply != nil {
- if reply.EntryName() == name {
- return fmt.Errorf("template object still exists: %s", name)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_panorama_template_variable_test.go b/assets/terraform/test/resource_panorama_template_variable_test.go
index 9e5dbd4f..67804d5a 100644
--- a/assets/terraform/test/resource_panorama_template_variable_test.go
+++ b/assets/terraform/test/resource_panorama_template_variable_test.go
@@ -1,19 +1,15 @@
package provider_test
import (
- "context"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/panorama/template_variable"
"github.com/hashicorp/terraform-plugin-testing/compare"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -77,11 +73,7 @@ func TestAccPanosPanoramaTemplateVariable(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccPanosPanoramaTemplateVariableDestroy(
- "$tempvar-"+nameSuffix,
- fmt.Sprintf("%s_%s", templateName, nameSuffix),
- ),
- Steps: templateVariableTypeEntries,
+ Steps: templateVariableTypeEntries,
})
}
@@ -119,26 +111,3 @@ func makePanoramaTemplateVariableConfig(label string) string {
return fmt.Sprintf(configTpl, label, label, label)
}
-
-func testAccPanosPanoramaTemplateVariableDestroy(entryName, templateName string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := template_variable.NewService(sdkClient)
- ctx := context.TODO()
-
- location := template_variable.NewTemplateLocation()
- location.Template.Template = templateName
-
- reply, err := api.Read(ctx, *location, entryName, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading template variable entry via sdk: %v", err)
- }
-
- if reply != nil {
- if reply.EntryName() == entryName {
- return fmt.Errorf("template object still exists: %s", entryName)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_security_policy_rules_test.go b/assets/terraform/test/resource_security_policy_rules_test.go
index 87baa2e0..9e13b00a 100644
--- a/assets/terraform/test/resource_security_policy_rules_test.go
+++ b/assets/terraform/test/resource_security_policy_rules_test.go
@@ -4,22 +4,17 @@ import (
"context"
"encoding/base64"
"encoding/json"
- "errors"
"fmt"
"regexp"
"strings"
"testing"
- sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/policies/rules/security"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
- //"github.com/hashicorp/terraform-plugin-testing/plancheck"
- //"github.com/PaloAltoNetworks/terraform-provider-panos/internal/provider"
- //"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
@@ -90,7 +85,6 @@ func TestAccSecurityPolicyRulesImport(t *testing.T) {
testAccPreCheck(t)
},
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: securityPolicyRulesCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: securityPolicyRulesImportInitial,
@@ -334,7 +328,6 @@ func TestAccSecurityPolicyRulesPositioning(t *testing.T) {
},
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: securityPolicyRulesCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: securityPolicyRulesPositionFirst,
@@ -704,7 +697,6 @@ func TestAccSecurityPolicyRulesPositionAsVariable(t *testing.T) {
},
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: securityPolicyRulesCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: securityPolicyRulesPositionAsVariableTmpl,
@@ -815,53 +807,6 @@ func securityPolicyRulesPreCheck(prefix string) {
}
}
-func securityPolicyRulesCheckDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
-
- location := security.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg", prefix)
-
- service := security.NewService(sdkClient)
- ctx := context.TODO()
-
- rules, err := service.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return err
- }
-
- var danglingNames []string
-
- seededRule := func(name string) bool {
- seeded := []string{"rule-0", "rule-1", "rule-99"}
- for _, elt := range seeded {
- if strings.HasSuffix(name, elt) {
- return true
- }
- }
-
- return false
- }
-
- for _, elt := range rules {
- if strings.HasPrefix(elt.Name, prefix) && !seededRule(elt.Name) {
- danglingNames = append(danglingNames, elt.Name)
- }
- }
-
- if len(danglingNames) > 0 {
- err := fmt.Errorf("%w: %s", DanglingObjectsError, strings.Join(danglingNames, ", "))
- delErr := service.Delete(ctx, *location, danglingNames...)
- if delErr != nil {
- err = errors.Join(err, delErr)
- }
-
- return err
- }
-
- return nil
- }
-}
-
func mergeConfigs(configs ...string) string {
return strings.Join(configs, "\n")
}
diff --git a/assets/terraform/test/resource_security_policy_test.go b/assets/terraform/test/resource_security_policy_test.go
index ae599a1e..e38a641c 100644
--- a/assets/terraform/test/resource_security_policy_test.go
+++ b/assets/terraform/test/resource_security_policy_test.go
@@ -2,13 +2,11 @@ package provider_test
import (
"context"
- "errors"
"fmt"
"regexp"
"strings"
"testing"
- sdkerrors "github.com/PaloAltoNetworks/pango/errors"
"github.com/PaloAltoNetworks/pango/policies/rules/security"
"github.com/hashicorp/terraform-plugin-testing/config"
@@ -17,7 +15,6 @@ import (
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -555,7 +552,6 @@ func TestAccSecurityPolicyOrdering(t *testing.T) {
},
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: securityPolicyCheckDestroy(prefix),
Steps: []resource.TestStep{
{
Config: securityPolicyOrderingTmpl,
@@ -683,37 +679,3 @@ func securityPolicyPreCheck(prefix string) {
}
}
-
-func securityPolicyCheckDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- service := security.NewService(sdkClient)
- ctx := context.TODO()
-
- location := security.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg", prefix)
-
- rules, err := service.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return err
- }
-
- var danglingNames []string
- for _, elt := range rules {
- if strings.HasPrefix(elt.Name, prefix) {
- danglingNames = append(danglingNames, elt.Name)
- }
- }
-
- if len(danglingNames) > 0 {
- err := DanglingObjectsError
- delErr := service.Delete(ctx, *location, danglingNames...)
- if delErr != nil {
- err = errors.Join(err, delErr)
- }
-
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_security_profile_test.go b/assets/terraform/test/resource_security_profile_test.go
index 3309412e..aeb816be 100644
--- a/assets/terraform/test/resource_security_profile_test.go
+++ b/assets/terraform/test/resource_security_profile_test.go
@@ -2,7 +2,6 @@ package provider_test
import (
"context"
- "errors"
"fmt"
"strings"
"testing"
@@ -15,7 +14,6 @@ import (
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,7 +26,6 @@ func TestAccSecurityProfileGroup(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccSecurityProfileGroupDestroy(prefix),
Steps: []resource.TestStep{
{
Config: securityProfileGroupTmpl,
@@ -178,35 +175,3 @@ func (o *securityProfileGroupExpectNoEntriesInLocation) CheckState(ctx context.C
resp.Error = fmt.Errorf("delete of the resource didn't remove it from the server")
}
}
-
-func testAccSecurityProfileGroupDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- service := secgroup.NewService(sdkClient)
-
- location := secgroup.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg1", prefix)
-
- ctx := context.TODO()
- entries, err := service.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return fmt.Errorf("failed to list existing entries via sdk: %w", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := service.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_service_group_test.go b/assets/terraform/test/resource_service_group_test.go
index 9280f078..3d6227dd 100644
--- a/assets/terraform/test/resource_service_group_test.go
+++ b/assets/terraform/test/resource_service_group_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkerrors "github.com/PaloAltoNetworks/pango/errors"
- servicegroup "github.com/PaloAltoNetworks/pango/objects/service/group"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,7 +21,6 @@ func TestAccPanosServiceGroup(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosServiceGroupDestroy(prefix),
Steps: []resource.TestStep{
{
Config: testAccPanosServiceGroupTmpl,
@@ -111,34 +103,3 @@ resource "panos_service_group" "group2" {
members = var.groups["group2"].members
}
`
-
-func testAccCheckPanosServiceGroupDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- svc := servicegroup.NewService(sdkClient)
- ctx := context.TODO()
- location := servicegroup.NewSharedLocation()
-
- entries, err := svc.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return fmt.Errorf("Failed to list service group entries: %w", err)
- }
-
- err = nil
- var dangling []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- dangling = append(dangling, elt.Name)
- err = errors.Join(err, fmt.Errorf("service group entry not deleted properly: %s", elt.Name))
- }
- }
-
- if len(dangling) > 0 {
- deleteErr := svc.Delete(ctx, *location, dangling...)
- if deleteErr != nil && !sdkerrors.IsObjectNotFound(deleteErr) {
- err = errors.Join(err, fmt.Errorf("failed to delete service group entries: %w", deleteErr))
- }
- }
-
- return err
- }
-}
diff --git a/assets/terraform/test/resource_service_test.go b/assets/terraform/test/resource_service_test.go
index 6f61afae..370002d6 100644
--- a/assets/terraform/test/resource_service_test.go
+++ b/assets/terraform/test/resource_service_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/objects/service"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,7 +21,6 @@ func TestAccService(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccServiceDestroy(prefix),
Steps: []resource.TestStep{
{
Config: testAccServiceResourceTmpl,
@@ -276,34 +268,3 @@ resource "panos_service" "svc4" {
protocol = var.services["svc4"].protocol
}
`
-
-func testAccServiceDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := service.NewService(sdkClient)
- ctx := context.TODO()
-
- location := service.NewSharedLocation()
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("listing interface management entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_url_filtering_security_profile_test.go b/assets/terraform/test/resource_url_filtering_security_profile_test.go
index fccae012..a91b0c87 100644
--- a/assets/terraform/test/resource_url_filtering_security_profile_test.go
+++ b/assets/terraform/test/resource_url_filtering_security_profile_test.go
@@ -2,7 +2,6 @@ package provider_test
import (
"context"
- "errors"
"fmt"
"strings"
"testing"
@@ -15,7 +14,6 @@ import (
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -26,7 +24,6 @@ func TestAccUrlFilteringSecurityProfile(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccUrlFilteringSecurityProfileDestroy(prefix),
Steps: []resource.TestStep{
{
Config: urlFilteringSecurityProfile1Tmpl,
@@ -293,35 +290,3 @@ func (o *urlFilteringSecurityProfileExpectNoEntriesInLocation) CheckState(ctx co
resp.Error = fmt.Errorf("delete of the resource didn't remove it from the server")
}
}
-
-func testAccUrlFilteringSecurityProfileDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- service := urlfiltering.NewService(sdkClient)
-
- location := urlfiltering.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg1", prefix)
-
- ctx := context.TODO()
- entries, err := service.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return fmt.Errorf("failed to list existing entries via sdk: %w", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := service.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_virtual_router_test.go b/assets/terraform/test/resource_virtual_router_test.go
index ec88fa86..07c2b873 100644
--- a/assets/terraform/test/resource_virtual_router_test.go
+++ b/assets/terraform/test/resource_virtual_router_test.go
@@ -1,18 +1,14 @@
package provider_test
import (
- "context"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/network/virtual_router"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -26,10 +22,6 @@ func TestAccPanosVirtualRouter_RequiredInputs(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosVirtualRouterDestroy(
- fmt.Sprintf("%s-%s", resName, nameSuffix),
- fmt.Sprintf("%s-%s", templateName, nameSuffix),
- ),
Steps: []resource.TestStep{
{
Config: makePanosVirtualRouterConfig(resName),
@@ -65,10 +57,6 @@ func TestAccPanosVirtualRouter_WithEthernetInterface(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosVirtualRouterDestroy(
- fmt.Sprintf("%s-%s", resName, nameSuffix),
- fmt.Sprintf("%s-%s", templateName, nameSuffix),
- ),
Steps: []resource.TestStep{
{
Config: makePanosVirtualRouterConfig(resName),
@@ -182,26 +170,3 @@ func makePanosVirtualRouterConfig(label string) string {
return fmt.Sprintf(configTpl, label)
}
-
-func testAccCheckPanosVirtualRouterDestroy(entryName, templateName string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := virtual_router.NewService(sdkClient)
- ctx := context.TODO()
-
- location := virtual_router.NewTemplateLocation()
- location.Template.Template = templateName
-
- reply, err := api.Read(ctx, *location, entryName, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading virtual router entry via sdk: %v", err)
- }
-
- if reply != nil {
- if reply.EntryName() == entryName {
- return fmt.Errorf("virtual router object still exists: %s", entryName)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_vlan_interface_test.go b/assets/terraform/test/resource_vlan_interface_test.go
index d565086b..1f8d813b 100644
--- a/assets/terraform/test/resource_vlan_interface_test.go
+++ b/assets/terraform/test/resource_vlan_interface_test.go
@@ -1,20 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/network/interface/vlan"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -28,9 +22,6 @@ func TestAccVlanInterface_1(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosVlanInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: vlanInterfaceResource1,
@@ -355,9 +346,6 @@ func TestAccVlanInterface_2(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosVlanInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: vlanInterfaceResource2,
@@ -534,9 +522,6 @@ func TestAccVlanInterface_3(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckPanosVlanInterfaceDestroy(
- prefix, interfaceName,
- ),
Steps: []resource.TestStep{
{
Config: vlanInterfaceResource3,
@@ -792,29 +777,3 @@ resource "panos_vlan_interface" "iface" {
}
}
`
-
-func testAccCheckPanosVlanInterfaceDestroy(prefix string, entry string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := vlan.NewService(sdkClient)
- ctx := context.TODO()
-
- location := vlan.NewTemplateLocation()
- location.Template.Template = fmt.Sprintf("%s-tmpl", prefix)
-
- reply, err := api.Read(ctx, *location, entry, "show")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("reading ethernet entry via sdk: %v", err)
- }
-
- if reply != nil {
- err := fmt.Errorf("terraform didn't delete the server entry properly")
- delErr := api.Delete(ctx, *location, entry)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- return err
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_vulnerability_security_profile_test.go b/assets/terraform/test/resource_vulnerability_security_profile_test.go
index b3adfca8..42376d58 100644
--- a/assets/terraform/test/resource_vulnerability_security_profile_test.go
+++ b/assets/terraform/test/resource_vulnerability_security_profile_test.go
@@ -1,10 +1,7 @@
-// In TestAccVulnerabilitySecurityProfile function implement all checks indicated by "MISSING" comment
-
package provider_test
import (
"context"
- "errors"
"fmt"
"strings"
"testing"
@@ -17,7 +14,6 @@ import (
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -30,7 +26,6 @@ func TestAccVulnerabilitySecurityProfile(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccVulnerabilitySecurityProfileDestroy(prefix),
Steps: []resource.TestStep{
{
Config: vulnerabilitySecurityProfileTmpl,
@@ -269,35 +264,3 @@ func (o *vulnerabilitySecurityProfileExpectNoEntriesInLocation) CheckState(ctx c
resp.Error = fmt.Errorf("delete of the resource didn't remove it from the server")
}
}
-
-func testAccVulnerabilitySecurityProfileDestroy(prefix string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- service := vulnerability.NewService(sdkClient)
-
- location := vulnerability.NewDeviceGroupLocation()
- location.DeviceGroup.DeviceGroup = fmt.Sprintf("%s-dg1", prefix)
-
- ctx := context.TODO()
- entries, err := service.List(ctx, *location, "get", "", "")
- if err != nil && !sdkerrors.IsObjectNotFound(err) {
- return fmt.Errorf("failed to list existing entries via sdk: %w", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := service.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/assets/terraform/test/resource_zone_test.go b/assets/terraform/test/resource_zone_test.go
index 3bbf881d..ece3b2da 100644
--- a/assets/terraform/test/resource_zone_test.go
+++ b/assets/terraform/test/resource_zone_test.go
@@ -1,21 +1,14 @@
package provider_test
import (
- "context"
- "errors"
"fmt"
- "strings"
"testing"
- sdkErrors "github.com/PaloAltoNetworks/pango/errors"
- "github.com/PaloAltoNetworks/pango/network/zone"
-
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
- "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)
@@ -29,7 +22,6 @@ func TestAccZone(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccZoneDestroy(prefix, fmt.Sprintf("%s-%s", prefix, suffix)),
Steps: []resource.TestStep{
{
Config: zoneResourceTmpl,
@@ -78,7 +70,6 @@ func TestAccZone(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccZoneDestroy(prefix, fmt.Sprintf("%s-%s", prefix, suffix)),
Steps: []resource.TestStep{
{
Config: zoneResourceTmpl,
@@ -96,7 +87,6 @@ func TestAccZone(t *testing.T) {
// resource.Test(t, resource.TestCase{
// PreCheck: func() { testAccPreCheck(t) },
// ProtoV6ProviderFactories: testAccProviders,
- // CheckDestroy: testAccZoneDestroy(prefix, fmt.Sprintf("%s-%s", prefix, suffix)),
// Steps: []resource.TestStep{
// {
// Config: zoneResourceTmpl,
@@ -114,7 +104,6 @@ func TestAccZone(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProviders,
- CheckDestroy: testAccZoneDestroy(prefix, fmt.Sprintf("%s-%s", prefix, suffix)),
Steps: []resource.TestStep{
{
Config: zoneResourceTmpl,
@@ -142,7 +131,6 @@ func TestAccZone(t *testing.T) {
// resource.Test(t, resource.TestCase{
// PreCheck: func() { testAccPreCheck(t) },
// ProtoV6ProviderFactories: testAccProviders,
- // CheckDestroy: testAccZoneDestroy(prefix, fmt.Sprintf("%s-%s", prefix, suffix)),
// Steps: []resource.TestStep{
// {
// Config: zoneResourceTmpl,
@@ -238,40 +226,3 @@ resource "panos_zone" "zone" {
network = local.network
}
`
-
-func testAccZoneDestroy(prefix string, template string) func(s *terraform.State) error {
- return func(s *terraform.State) error {
- api := zone.NewService(sdkClient)
- ctx := context.TODO()
-
- location := zone.NewTemplateLocation()
- location.Template = &zone.TemplateLocation{
- Template: template,
- Vsys: "vsys1",
- NgfwDevice: "localhost.localdomain",
- PanoramaDevice: "localhost.localdomain",
- }
-
- entries, err := api.List(ctx, *location, "get", "", "")
- if err != nil && !sdkErrors.IsObjectNotFound(err) {
- return fmt.Errorf("error while listing entries via sdk: %v", err)
- }
-
- var leftEntries []string
- for _, elt := range entries {
- if strings.HasPrefix(elt.Name, prefix) {
- leftEntries = append(leftEntries, elt.Name)
- }
- }
-
- if len(leftEntries) > 0 {
- err := fmt.Errorf("terraform failed to remove entries from the server")
- delErr := api.Delete(ctx, *location, leftEntries...)
- if delErr != nil {
- return errors.Join(err, delErr)
- }
- }
-
- return nil
- }
-}
diff --git a/pkg/generate/generator.go b/pkg/generate/generator.go
index 7111eea6..dbf65400 100644
--- a/pkg/generate/generator.go
+++ b/pkg/generate/generator.go
@@ -250,17 +250,17 @@ func writeContentToFile(content *bytes.Buffer, file *os.File) error {
func (c *Creator) parseTemplate(templateName string) (*template.Template, error) {
templatePath := filepath.Join(c.TemplatesDir, templateName)
funcMap := template.FuncMap{
- "Map": codegentmpl.TemplateMap,
- "renderImports": translate.RenderImports,
+ "Map": codegentmpl.TemplateMap,
+ "renderImports": func(templateTypes ...string) (string, error) {
+ return translate.RenderImports(c.Spec, templateTypes...)
+ },
"RenderEntryImportStructs": func() (string, error) { return translate.RenderEntryImportStructs(c.Spec) },
"packageName": translate.PackageName,
"locationType": translate.LocationType,
"specParamType": translate.SpecParamType,
- "xmlParamType": translate.XmlParamType,
"xmlName": translate.XmlName,
+ "xmlParamType": translate.XmlParamType,
"xmlTag": translate.XmlTag,
- "specifyEntryAssignment": translate.SpecifyEntryAssignmentTmpl,
- "normalizeAssignment": translate.NormalizeAssignmentTmpl,
"specMatchesFunction": translate.SpecMatchesFunction,
"nestedSpecMatchesFunction": translate.NestedSpecMatchesFunction,
"omitEmpty": translate.OmitEmpty,
@@ -271,13 +271,32 @@ func (c *Creator) parseTemplate(templateName string) (*template.Template, error)
"subtract": func(a, b int) int {
return a - b
},
- "generateEntryXpath": translate.GenerateEntryXpath,
- "nestedSpecs": translate.NestedSpecs,
+ "generateEntryXpath": translate.GenerateEntryXpath,
+ "RenderApiStructs": func(spec *properties.Normalization) (string, error) {
+ return translate.RenderEntryApiStructs(spec)
+ },
+ "RenderXmlStructs": func(spec *properties.Normalization) (string, error) {
+ return translate.RenderEntryXmlStructs(spec)
+ },
+ "RenderXmlContainerNormalizers": func(spec *properties.Normalization) (string, error) {
+ return translate.RenderXmlContainerNormalizers(spec)
+ },
+ "RenderXmlContainerSpecifiers": func(spec *properties.Normalization) (string, error) {
+ return translate.RenderXmlContainerSpecifiers(spec)
+ },
+ "RenderToXmlMarshallers": func(spec *properties.Normalization) (string, error) {
+ return translate.RenderToXmlMarshalers(spec)
+ },
+ "RenderSpecMatchers": func(spec *properties.Normalization) (string, error) {
+ return translate.RenderSpecMatchers(spec)
+ },
"createGoSuffixFromVersion": translate.CreateGoSuffixFromVersionTmpl,
+ "paramNotSkipped": translate.ParamNotSkippedTmpl,
"paramSupportedInVersion": translate.ParamSupportedInVersionTmpl,
"xmlPathSuffixes": translate.XmlPathSuffixes,
"underscore": naming.Underscore,
"camelCase": naming.CamelCase,
+ "lowerCamelCase": naming.LowerCamelCase,
}
return template.New(templateName).Funcs(funcMap).ParseFiles(templatePath)
}
diff --git a/pkg/naming/names.go b/pkg/naming/names.go
index 222942c6..dab0b8c7 100644
--- a/pkg/naming/names.go
+++ b/pkg/naming/names.go
@@ -92,6 +92,13 @@ func CamelCase(prefix, value, suffix string, capitalizeFirstRune bool) string {
return builder.String()
}
+func LowerCamelCase(value string) string {
+ r := []rune(value)
+ r[0] = unicode.ToLower(r[0])
+
+ return string(r)
+}
+
// writeRuneAndApplyChangesForCamelCase contains logic to check all conditions for create CamelCase names and writes rune value.
func writeRuneAndApplyChangesForCamelCase(runeValue int32, builder *strings.Builder, isFirstCharacter *bool, hasFirstRuneBeenCapitalized *bool, capitalizeFirstRune *bool) {
if shouldResetFirstCharacterFlag(runeValue) {
diff --git a/pkg/properties/namevariant.go b/pkg/properties/namevariant.go
new file mode 100644
index 00000000..f54c6819
--- /dev/null
+++ b/pkg/properties/namevariant.go
@@ -0,0 +1,48 @@
+package properties
+
+import (
+ "strings"
+
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/naming"
+)
+
+type NameVariant struct {
+ Original string
+ Underscore string
+ CamelCase string
+ LowerCamelCase string
+}
+
+func NewNameVariant(name string) *NameVariant {
+ return &NameVariant{
+ Original: name,
+ Underscore: naming.Underscore("", name, ""),
+ CamelCase: naming.CamelCase("", name, "", true),
+ LowerCamelCase: naming.CamelCase("", name, "", false),
+ }
+}
+
+func (o NameVariant) Components() []string {
+ return strings.Split(o.Original, "-")
+}
+
+func (o NameVariant) IsEmpty() bool {
+ return o.Original == ""
+}
+
+func (o NameVariant) WithSuffix(suffix *NameVariant) *NameVariant {
+ if o.Original == "" {
+ return NewNameVariant(suffix.Original)
+ } else {
+ return NewNameVariant(o.Original + "-" + suffix.Original)
+ }
+}
+
+func (o NameVariant) WithLiteralSuffix(suffix string) *NameVariant {
+ return &NameVariant{
+ Original: o.Original + suffix,
+ CamelCase: o.CamelCase + suffix,
+ LowerCamelCase: o.LowerCamelCase + suffix,
+ Underscore: o.Underscore + suffix,
+ }
+}
diff --git a/pkg/properties/namevariant_test.go b/pkg/properties/namevariant_test.go
new file mode 100644
index 00000000..8a76061d
--- /dev/null
+++ b/pkg/properties/namevariant_test.go
@@ -0,0 +1,22 @@
+package properties_test
+
+import (
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
+)
+
+var _ = Describe("NameVariant", func() {
+ Context("When creating name variant from empty string", func() {
+ It("should return empty string for all variants", func() {
+ variant := properties.NewNameVariant("")
+ Expect(variant).To(Equal(&properties.NameVariant{
+ Original: "",
+ LowerCamelCase: "",
+ CamelCase: "",
+ Underscore: "",
+ }))
+ })
+ })
+})
diff --git a/pkg/properties/normalized.go b/pkg/properties/normalized.go
index ed6c89e9..6819df2f 100644
--- a/pkg/properties/normalized.go
+++ b/pkg/properties/normalized.go
@@ -1,17 +1,19 @@
package properties
import (
+ "bytes"
"fmt"
"io/fs"
"maps"
"path/filepath"
+ "regexp"
"runtime"
"slices"
"strconv"
"strings"
+ "text/template"
"github.com/paloaltonetworks/pan-os-codegen/pkg/content"
- "github.com/paloaltonetworks/pan-os-codegen/pkg/naming"
"github.com/paloaltonetworks/pan-os-codegen/pkg/schema/object"
"github.com/paloaltonetworks/pan-os-codegen/pkg/schema/parameter"
"github.com/paloaltonetworks/pan-os-codegen/pkg/schema/validator"
@@ -24,7 +26,7 @@ type Normalization struct {
TerraformProviderConfig TerraformProviderConfig `json:"terraform_provider_config" yaml:"terraform_provider_config"`
GoSdkSkip bool `json:"go_sdk_skip" yaml:"go_sdk_skip"`
GoSdkPath []string `json:"go_sdk_path" yaml:"go_sdk_path"`
- XpathSuffix []string `json:"xpath_suffix" yaml:"xpath_suffix"`
+ PanosXpath PanosXpath `json:"panos_xpath" yaml:"panos_xpath"`
Locations map[string]*Location `json:"locations" yaml:"locations"`
Entry *Entry `json:"entry" yaml:"entry"`
Imports []Import `json:"imports" yaml:"imports"`
@@ -33,6 +35,11 @@ type Normalization struct {
Const map[string]*Const `json:"const" yaml:"const"`
}
+type PanosXpath struct {
+ Path []string `yaml:"path"`
+ Variables []object.PanosXpathVariable `yaml:"vars"`
+}
+
type Import struct {
Variant *NameVariant
Type *NameVariant
@@ -82,25 +89,10 @@ type TerraformProviderConfig struct {
Suffix string `json:"suffix" yaml:"suffix"`
PluralSuffix string `json:"plural_suffix" yaml:"plural_suffix"`
PluralName string `json:"plural_name" yaml:"plural_name"`
+ PluralType object.TerraformPluralType `json:"plural_type" yaml:"plural_type"`
PluralDescription string `json:"plural_description" yaml:"plural_description"`
}
-type NameVariant struct {
- Original string
- Underscore string
- CamelCase string
- LowerCamelCase string
-}
-
-func NewNameVariant(name string) *NameVariant {
- return &NameVariant{
- Original: name,
- Underscore: naming.Underscore("", name, ""),
- CamelCase: naming.CamelCase("", name, "", true),
- LowerCamelCase: naming.CamelCase("", name, "", false),
- }
-}
-
type Location struct {
Name *NameVariant
SpecOrder int
@@ -182,6 +174,7 @@ type SpecParam struct {
SpecOrder int `json:"-" yaml:"-"`
Description string `json:"description" yaml:"description"`
TerraformProviderConfig *SpecParamTerraformProviderConfig `json:"terraform_provider_config" yaml:"terraform_provider_config"`
+ GoSdkConfig *SpecParamGoSdkConfig `json:"gosdk_config" yaml:"gosdk_config"`
IsNil bool `json:"-" yaml:"-"`
Type string `json:"type" yaml:"type"`
Default string `json:"default" yaml:"default"`
@@ -197,14 +190,19 @@ type SpecParam struct {
Spec *Spec `json:"spec" yaml:"spec"`
}
+type SpecParamGoSdkConfig struct {
+ Skip *bool `json:"skip" yaml:"skip"`
+}
+
type SpecParamTerraformProviderConfig struct {
- Name *string `json:"name" yaml:"name"`
- Type *string `json:"type" yaml:"type"`
- Private *bool `json:"ignored" yaml:"private"`
- Sensitive *bool `json:"sensitive" yaml:"sensitive"`
- Computed *bool `json:"computed" yaml:"computed"`
- Required *bool `json:"required" yaml:"required"`
- VariantCheck *string `json:"variant_check" yaml:"variant_check"`
+ Name *string `json:"name" yaml:"name"`
+ Type *string `json:"type" yaml:"type"`
+ Private *bool `json:"ignored" yaml:"private"`
+ Sensitive *bool `json:"sensitive" yaml:"sensitive"`
+ Computed *bool `json:"computed" yaml:"computed"`
+ Required *bool `json:"required" yaml:"required"`
+ VariantCheck *string `json:"variant_check" yaml:"variant_check"`
+ XpathVariable *string `json:"xpath_variable" yaml:"xpath_variable"`
}
type SpecParamLength struct {
@@ -425,6 +423,14 @@ func (o *SpecParam) HasPrivateParameters() bool {
return false
}
+func (o *SpecParam) IsTerraformOnly() bool {
+ if o.GoSdkConfig != nil && o.GoSdkConfig.Skip != nil {
+ return *o.GoSdkConfig.Skip
+ }
+
+ return false
+}
+
func (o *SpecParam) IsPrivateParameter() bool {
if o.TerraformProviderConfig != nil && o.TerraformProviderConfig.Private != nil {
return *o.TerraformProviderConfig.Private
@@ -569,6 +575,7 @@ func schemaParameterToSpecParameter(schemaSpec *parameter.Parameter) (*SpecParam
}
var terraformProviderConfig *SpecParamTerraformProviderConfig
+ var goSdkConfig *SpecParamGoSdkConfig
if schemaSpec.CodegenOverrides != nil {
var variantCheck *string
if schemaSpec.CodegenOverrides.Terraform.VariantCheck != nil {
@@ -577,13 +584,18 @@ func schemaParameterToSpecParameter(schemaSpec *parameter.Parameter) (*SpecParam
}
terraformProviderConfig = &SpecParamTerraformProviderConfig{
- Name: schemaSpec.CodegenOverrides.Terraform.Name,
- Type: schemaSpec.CodegenOverrides.Terraform.Type,
- Private: schemaSpec.CodegenOverrides.Terraform.Private,
- Sensitive: schemaSpec.CodegenOverrides.Terraform.Sensitive,
- Computed: schemaSpec.CodegenOverrides.Terraform.Computed,
- Required: schemaSpec.CodegenOverrides.Terraform.Required,
- VariantCheck: variantCheck,
+ Name: schemaSpec.CodegenOverrides.Terraform.Name,
+ Type: schemaSpec.CodegenOverrides.Terraform.Type,
+ Private: schemaSpec.CodegenOverrides.Terraform.Private,
+ Sensitive: schemaSpec.CodegenOverrides.Terraform.Sensitive,
+ Computed: schemaSpec.CodegenOverrides.Terraform.Computed,
+ Required: schemaSpec.CodegenOverrides.Terraform.Required,
+ VariantCheck: variantCheck,
+ XpathVariable: schemaSpec.CodegenOverrides.Terraform.XpathVariable,
+ }
+
+ goSdkConfig = &SpecParamGoSdkConfig{
+ Skip: schemaSpec.CodegenOverrides.GoSdk.Skip,
}
}
@@ -593,6 +605,7 @@ func schemaParameterToSpecParameter(schemaSpec *parameter.Parameter) (*SpecParam
IsNil: paramTypeIsNil,
Default: defaultVal,
Required: schemaSpec.Required,
+ GoSdkConfig: goSdkConfig,
TerraformProviderConfig: terraformProviderConfig,
Hashing: specHashing,
Profiles: profiles,
@@ -665,6 +678,12 @@ func schemaToSpec(object object.Object) (*Normalization, error) {
for _, elt := range object.TerraformConfig.ResourceVariants {
resourceVariants = append(resourceVariants, TerraformResourceVariant(elt))
}
+
+ panosXpath := PanosXpath{
+ Path: object.PanosXpath.Path,
+ Variables: object.PanosXpath.Variables,
+ }
+
spec := &Normalization{
Name: object.DisplayName,
TerraformProviderConfig: TerraformProviderConfig{
@@ -679,13 +698,14 @@ func schemaToSpec(object object.Object) (*Normalization, error) {
Suffix: object.TerraformConfig.Suffix,
PluralSuffix: object.TerraformConfig.PluralSuffix,
PluralName: object.TerraformConfig.PluralName,
+ PluralType: object.TerraformConfig.PluralType,
PluralDescription: object.TerraformConfig.PluralDescription,
},
- Locations: make(map[string]*Location),
- GoSdkSkip: object.GoSdkConfig.Skip,
- GoSdkPath: object.GoSdkConfig.Package,
- XpathSuffix: object.XpathSuffix,
- Version: object.Version,
+ Locations: make(map[string]*Location),
+ GoSdkSkip: object.GoSdkConfig.Skip,
+ GoSdkPath: object.GoSdkConfig.Package,
+ PanosXpath: panosXpath,
+ Version: object.Version,
Spec: &Spec{
Params: make(map[string]*SpecParam),
OneOf: make(map[string]*SpecParam),
@@ -1042,6 +1062,217 @@ func (spec *Normalization) Sanity() error {
return nil
}
+func (spec *Normalization) XpathSuffix() []string {
+ return spec.PanosXpath.Path
+}
+
+func (spec *Normalization) ResourceXpathVariablesWithChecks(checkEntryName bool) bool {
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "name" && !checkEntryName {
+ continue
+ }
+
+ if elt.Spec.Type != "value" {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (spec *Normalization) ResourceXpathVariablesCount() int {
+ if spec.HasEntryName() && len(spec.PanosXpath.Variables) == 0 {
+ return 1
+ }
+
+ return len(spec.PanosXpath.Variables)
+}
+
+const attributesFromXpathComponentsTmpl = `
+{{- range .Components }}
+ {{ if eq .Type "value" }}
+ {{ $.Target }}.{{ .Name }} = types.StringValue(components[{{ .Idx }}])
+ {{- else if eq .Type "entry" }}
+{
+ component := components[{{ .Idx }}]
+ component = strings.TrimPrefix(component, "entry[@name='")
+ component = strings.TrimSuffix(component, "']")
+ {{ $.Target }}.{{ .Name.CamelCase }} = types.StringValue(component)
+}
+ {{- end }}
+{{- end }}
+`
+
+func (spec *Normalization) AttributesFromXpathComponents(target string) (string, error) {
+ type componentCtx struct {
+ Type object.PanosXpathVariableType
+ Name *NameVariant
+ Idx int
+ }
+
+ type componentsCtx struct {
+ Target string
+ Components []componentCtx
+ }
+
+ var components []componentCtx
+ for idx, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "name" {
+ continue
+ }
+
+ param, err := spec.ParameterForPanosXpathVariable(elt)
+ if err != nil {
+ return "", err
+ }
+
+ components = append(components, componentCtx{
+ Type: elt.Spec.Type,
+ Name: param.Name,
+ Idx: idx,
+ })
+ }
+
+ data := componentsCtx{
+ Target: target,
+ Components: components,
+ }
+
+ tmpl := template.Must(template.New("attributes-from-xpath-components").Parse(attributesFromXpathComponentsTmpl))
+
+ var buf bytes.Buffer
+ err := tmpl.Execute(&buf, data)
+ if err != nil {
+ panic(err)
+ }
+
+ return buf.String(), nil
+}
+
+const resourceXpathAssignmentsTmpl = `
+{{- range .Variables }}
+ {{- if or (eq .Type "entry") (eq .Type "value") }}
+ ans = append(ans, components[{{ .Idx }}])
+ {{- else if eq .Type "static" }}
+ ans = append(ans, "{{ .Name.Original }}")
+ {{- end }}
+{{- end }}
+`
+
+func (spec *Normalization) ResourceXpathAssignments() (string, error) {
+ data := xpathVariablesCtx{
+ Variables: createXpathVariablesContext(spec),
+ }
+
+ tmpl := template.Must(template.New("resource-xpath-assignments").Parse(resourceXpathAssignmentsTmpl))
+
+ var buf bytes.Buffer
+ err := tmpl.Execute(&buf, data)
+ if err != nil {
+ panic(err)
+ }
+
+ return buf.String(), nil
+}
+
+const xpathVariableChecksTmpl = `
+{{- range .Variables }}
+ {{- if eq .Type "entry" }}
+{
+ component := components[{{ .Idx }}]
+ {{- if .AllowEmpty }}
+ if component != "entry" {
+ {{- end }}
+ if !strings.HasPrefix(component, "entry[@name=\"]") && !strings.HasPrefix(component, "entry[@name='") {
+ return nil, errors.NewInvalidXpathComponentError(fmt.Sprintf("{{ .Name.CamelCase }} must be formatted as entry: %s", component))
+ }
+
+ if !strings.HasSuffix(component, "\"]") && !strings.HasSuffix(component, "']") {
+ return nil, errors.NewInvalidXpathComponentError(fmt.Sprintf("{{ .Name.CamelCase }} must be formatted as entry: %s", component))
+ }
+ {{- if .AllowEmpty }}
+ }
+ {{- end }}
+}
+ {{- end }}
+{{- end }}
+`
+
+type xpathVariableCtx struct {
+ Type object.PanosXpathVariableType
+ Name *NameVariant
+ AllowEmpty bool
+ Idx int
+}
+
+type xpathVariablesCtx struct {
+ Variables []xpathVariableCtx
+}
+
+func createXpathVariablesContext(spec *Normalization) []xpathVariableCtx {
+ var variables []xpathVariableCtx
+
+ variablesByName := make(map[string]object.PanosXpathVariable)
+ for _, elt := range spec.PanosXpath.Variables {
+ variablesByName[elt.Name] = elt
+ }
+
+ var idx int
+ for _, elt := range spec.PanosXpath.Path {
+ if strings.HasPrefix(elt, "$") {
+ variable, found := variablesByName[elt[1:]]
+ if !found {
+ panic("couldn't match panos xpath variable to path item")
+ }
+
+ var allowEmpty bool
+ var name *NameVariant
+ if variable.Name == "name" {
+ allowEmpty = true
+ name = NewNameVariant("name")
+ } else {
+ param, err := spec.ParameterForPanosXpathVariable(variable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+ name = param.Name
+ }
+
+ variables = append(variables, xpathVariableCtx{
+ Type: variable.Spec.Type,
+ AllowEmpty: allowEmpty,
+ Name: name,
+ Idx: idx,
+ })
+
+ idx += 1
+ } else {
+ variables = append(variables, xpathVariableCtx{
+ Type: object.PanosXpathVariableStatic,
+ Name: NewNameVariant(elt),
+ })
+ }
+ }
+
+ return variables
+}
+
+func (spec *Normalization) ResourceXpathVariableChecks() (string, error) {
+ data := xpathVariablesCtx{
+ Variables: createXpathVariablesContext(spec),
+ }
+
+ var buf bytes.Buffer
+ tmpl := template.Must(template.New("xpath-variable-checks").Parse(xpathVariableChecksTmpl))
+
+ err := tmpl.Execute(&buf, data)
+ if err != nil {
+ panic(err)
+ }
+
+ return buf.String(), nil
+}
+
// Validate validations for specification (normalization) e.g. check if XPath contain /.
func (spec *Normalization) Validate() []error {
var checks []error
@@ -1049,7 +1280,7 @@ func (spec *Normalization) Validate() []error {
if strings.Contains(spec.TerraformProviderConfig.Suffix, "panos_") {
checks = append(checks, fmt.Errorf("suffix for Terraform provider cannot contain `panos_`"))
}
- for _, suffix := range spec.XpathSuffix {
+ for _, suffix := range spec.XpathSuffix() {
if strings.Contains(suffix, "/") {
checks = append(checks, fmt.Errorf("XPath cannot contain /"))
}
@@ -1287,6 +1518,53 @@ func (spec *Normalization) HasPrivateParameters() bool {
return false
}
+func resolveXpath(xpath []string, spec *Spec) (*SpecParam, error) {
+ fmt.Printf("xpath[0]: %s\n", xpath[0])
+ elt := xpath[0]
+ if elt == "spec" {
+ elt = xpath[1]
+ }
+
+ var stack map[string]*SpecParam
+ if strings.HasPrefix(elt, "params") {
+ stack = spec.Params
+ } else if strings.HasPrefix(elt, "variants") {
+ stack = spec.OneOf
+ } else {
+ return nil, fmt.Errorf("failed to resolve variable xpath: %s", elt)
+ }
+
+ getParamNameFromXpathElt := func(elt string) string {
+ nameRegex := regexp.MustCompile(`.+("|')(?P.+)("|')`)
+ regexNames := nameRegex.SubexpNames()
+ matches := nameRegex.FindStringSubmatch(elt)
+
+ return matches[nameRegex.SubexpIndex(regexNames[2])]
+ }
+
+ name := getParamNameFromXpathElt(elt)
+
+ needle, found := stack[name]
+ if !found {
+ return nil, fmt.Errorf("failed to revolve variable xpath: %s", elt)
+ }
+
+ if len(xpath) == 1 {
+ return needle, nil
+ }
+
+ if needle.Spec == nil {
+ return nil, fmt.Errorf("failed to revolve variable xpath: %s", elt)
+ }
+
+ return resolveXpath(xpath[1:], needle.Spec)
+}
+
+func (spec *Normalization) ParameterForPanosXpathVariable(variable object.PanosXpathVariable) (*SpecParam, error) {
+ xpath := strings.Split(variable.Spec.Xpath, "/")
+ return resolveXpath(xpath[1:], spec.Spec)
+}
+
func supportedVersions(params map[string]*SpecParam, versions []string) []string {
for _, param := range params {
for _, profile := range param.Profiles {
diff --git a/pkg/properties/properties_suite_test.go b/pkg/properties/properties_suite_test.go
new file mode 100644
index 00000000..e59e4a36
--- /dev/null
+++ b/pkg/properties/properties_suite_test.go
@@ -0,0 +1,18 @@
+package properties_test
+
+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, "Properties Suite")
+}
diff --git a/pkg/schema/object/object.go b/pkg/schema/object/object.go
index a973bdef..60fe00d2 100644
--- a/pkg/schema/object/object.go
+++ b/pkg/schema/object/object.go
@@ -1,6 +1,8 @@
package object
import (
+ "fmt"
+
"gopkg.in/yaml.v3"
"github.com/paloaltonetworks/pan-os-codegen/pkg/schema/imports"
@@ -25,6 +27,14 @@ const (
TerraformResourcePlural TerraformResourceVariant = "plural"
)
+type TerraformPluralType string
+
+const (
+ TerraformPluralListType TerraformPluralType = "list"
+ TerraformPluralMapType TerraformPluralType = "map"
+ TerraformPluralSetType TerraformPluralType = "set"
+)
+
type TerraformConfig struct {
Description string `yaml:"description"`
Epheneral bool `yaml:"ephemeral"`
@@ -37,6 +47,7 @@ type TerraformConfig struct {
Suffix string `yaml:"suffix"`
PluralSuffix string `yaml:"plural_suffix"`
PluralName string `yaml:"plural_name"`
+ PluralType TerraformPluralType `yaml:"plural_type"`
PluralDescription string `yaml:"plural_description"`
}
@@ -57,10 +68,33 @@ type Spec struct {
Variants []*parameter.Parameter `yaml:"variants"`
}
+type PanosXpathVariableType string
+
+const (
+ PanosXpathVariableStatic PanosXpathVariableType = "static"
+ PanosXpathVariableValue PanosXpathVariableType = "value"
+ PanosXpathVariableEntry PanosXpathVariableType = "entry"
+)
+
+type PanosXpathVariableSpec struct {
+ Type PanosXpathVariableType `yaml:"type"`
+ Xpath string `yaml:"xpath"`
+}
+
+type PanosXpathVariable struct {
+ Name string `yaml:"name"`
+ Spec PanosXpathVariableSpec `yaml:"spec"`
+}
+
+type PanosXpath struct {
+ Path []string `yaml:"path"`
+ Variables []PanosXpathVariable `yaml:"vars"`
+}
+
type Object struct {
Name string `yaml:"-"`
DisplayName string `yaml:"name"`
- XpathSuffix []string `yaml:"xpath_suffix"`
+ PanosXpath PanosXpath `yaml:"panos_xpath"`
TerraformConfig *TerraformConfig `yaml:"terraform_provider_config"`
Version string `yaml:"version"`
GoSdkConfig *GoSdkConfig `yaml:"go_sdk_config"`
@@ -70,6 +104,47 @@ type Object struct {
Spec *Spec `yaml:"spec"`
}
+func (o *Object) UnmarshalYAML(n *yaml.Node) error {
+ type O Object
+ type S struct {
+ *O `yaml:",inline"`
+ }
+
+ obj := &S{O: (*O)(o)}
+ if err := n.Decode(obj); err != nil {
+ return err
+ }
+
+ switch obj.TerraformConfig.ResourceType {
+ case TerraformResourceEntry, TerraformResourceUuid:
+ if obj.PanosXpath.Path[len(obj.PanosXpath.Path)-1] != "$name" {
+ obj.PanosXpath.Path = append(obj.PanosXpath.Path, "$name")
+ obj.PanosXpath.Variables = append(obj.PanosXpath.Variables, PanosXpathVariable{
+ Name: "name",
+ Spec: PanosXpathVariableSpec{
+ Type: PanosXpathVariableEntry,
+ Xpath: "/params[@name=\"name\"]",
+ },
+ })
+ }
+ case TerraformResourceCustom, TerraformResourceConfig:
+ }
+
+ if obj.TerraformConfig.PluralType == "" {
+ switch obj.TerraformConfig.ResourceType {
+ case TerraformResourceUuid:
+ obj.TerraformConfig.PluralType = TerraformPluralListType
+ case TerraformResourceEntry:
+ obj.TerraformConfig.PluralType = TerraformPluralMapType
+ case TerraformResourceConfig, TerraformResourceCustom:
+ }
+ } else if obj.TerraformConfig.ResourceType == TerraformResourceUuid && obj.TerraformConfig.PluralType != "list" {
+ return fmt.Errorf("failed to unmarshal yaml spec: plural_type must be list for uuid resource types")
+ }
+
+ return nil
+}
+
func NewFromBytes(name string, objectBytes []byte) (*Object, error) {
var object Object
diff --git a/pkg/schema/parameter/parameter.go b/pkg/schema/parameter/parameter.go
index 79cc847d..af133a4d 100644
--- a/pkg/schema/parameter/parameter.go
+++ b/pkg/schema/parameter/parameter.go
@@ -3,6 +3,7 @@ package parameter
import (
"fmt"
"log/slog"
+ "strings"
"gopkg.in/yaml.v3"
@@ -50,17 +51,23 @@ const (
VariantCheckExactlyOneOf VariantCheckType = "ExactlyOneOf"
)
+type CodegenOverridesGoSdk struct {
+ Skip *bool `yaml:"skip"`
+}
+
type CodegenOverridesTerraform struct {
- Name *string `yaml:"name"`
- Type *string `yaml:"type"`
- Private *bool `yaml:"private"`
- Sensitive *bool `yaml:"sensitive"`
- Computed *bool `yaml:"computed"`
- Required *bool `yaml:"required"`
- VariantCheck *VariantCheckType `yaml:"variant_check"`
+ Name *string `yaml:"name"`
+ Type *string `yaml:"type"`
+ Private *bool `yaml:"private"`
+ Sensitive *bool `yaml:"sensitive"`
+ Computed *bool `yaml:"computed"`
+ Required *bool `yaml:"required"`
+ VariantCheck *VariantCheckType `yaml:"variant_check"`
+ XpathVariable *string `yaml:"xpath_variable"`
}
type CodegenOverrides struct {
+ GoSdk CodegenOverridesGoSdk `yaml:"gosdk"`
Terraform CodegenOverridesTerraform `yaml:"terraform"`
}
@@ -149,6 +156,9 @@ func (p *Parameter) UnmarshalYAML(n *yaml.Node) error {
return errors.NewSchemaError(fmt.Sprintf("unsupported parameter type: '%s'", p.Type))
}
+ // Escape value of a description, making sure all backslashes are handled properly
+ obj.Description = strings.ReplaceAll(obj.Description, "\\", "\\\\")
+
// Finally, decode obj.Spec (which is yaml.Node type) into the parameter
// spec structure
return obj.Spec.Decode(p.Spec)
diff --git a/pkg/translate/assignments.go b/pkg/translate/assignments.go
index f1f1d6ff..4729bb3d 100644
--- a/pkg/translate/assignments.go
+++ b/pkg/translate/assignments.go
@@ -1,86 +1,9 @@
package translate
import (
- "fmt"
- "log"
- "strings"
-
"github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
- "github.com/paloaltonetworks/pan-os-codegen/pkg/version"
)
-func NormalizeAssignmentTmpl(objectType string, param *properties.SpecParam, v any) (string, error) {
- if v != nil {
- typed, ok := v.(version.Version)
- if !ok {
- return "", fmt.Errorf("Failed to cast version to version.Version: '%T'", v)
- }
- return NormalizeAssignment(objectType, param, &typed), nil
- }
- return NormalizeAssignment(objectType, param, nil), nil
-}
-
-// NormalizeAssignment generates a string, which contains entry/config assignment in Normalize() function
-// in entry.tmpl/config.tmpl template. If param contains nested specs, then recursively are executed
-// internal functions, which are creating entry assignment.
-func NormalizeAssignment(objectType string, param *properties.SpecParam, version *version.Version) string {
- return prepareAssignment(objectType, param, "util.MemToStr", "util.EntToStr", "util.AsBool", "", "", version)
-}
-
-func SpecifyEntryAssignmentTmpl(objectType string, param *properties.SpecParam, v any) (string, error) {
-
- if v != nil {
- typed, ok := v.(version.Version)
- if !ok {
- return "", fmt.Errorf("Failed to cast version to version.Version: '%T'", v)
- }
- return SpecifyEntryAssignment(objectType, param, &typed), nil
- }
-
- return SpecifyEntryAssignment(objectType, param, nil), nil
-}
-
-// SpecifyEntryAssignment generates a string, which contains entry/config assignment in SpecifyEntry() function
-// in entry.tmpl/config.tmpl template. If param contains nested specs, then recursively are executed
-// internal functions, which are creating entry assignment.
-func SpecifyEntryAssignment(objectType string, param *properties.SpecParam, v *version.Version) string {
- return prepareAssignment(objectType, param, "util.StrToMem", "util.StrToEnt", "util.YesNo", "", "Xml", v)
-}
-
-func prepareAssignment(objectType string, param *properties.SpecParam, listFunction, entryFunction, boolFunction, prefix, suffix string, version *version.Version) string {
- var builder strings.Builder
-
- if ParamSupportedInVersion(param, version) {
- var isNestedListHack bool
- if param.Type == "list" {
- isNestedListHack = true
- }
- switch {
- case param.Spec != nil:
- appendSpecObjectAssignment(param, nil, objectType, version,
- listFunction, entryFunction, boolFunction, prefix, suffix, &builder, isNestedListHack)
- case isParamListAndProfileTypeIsMember(param):
- appendFunctionAssignment(param, objectType, listFunction, "", &builder)
- case isParamListAndProfileTypeIsSingleEntry(param):
- appendFunctionAssignment(param, objectType, entryFunction, "", &builder)
- case param.Type == "bool":
- appendFunctionAssignment(param, objectType, boolFunction,
- useBoolFunctionForAdditionalArguments(suffix, param), &builder)
- default:
- appendSimpleAssignment(param, objectType, &builder)
- }
- }
-
- return builder.String()
-}
-
-func useBoolFunctionForAdditionalArguments(suffix string, param *properties.SpecParam) string {
- if suffix == "Xml" && param.Default != "" {
- return fmt.Sprintf("util.Bool(%s)", param.Default)
- }
- return "nil"
-}
-
func isParamListAndProfileTypeIsMember(param *properties.SpecParam) bool {
return param.Type == "list" && param.Profiles != nil && len(param.Profiles) > 0 && param.Profiles[0].Type == "member"
}
@@ -92,293 +15,3 @@ func isParamListAndProfileTypeIsSingleEntry(param *properties.SpecParam) bool {
func isParamListAndProfileTypeIsExtendedEntry(param *properties.SpecParam) bool {
return param != nil && param.Type == "list" && param.Profiles != nil && len(param.Profiles) > 0 && param.Profiles[0].Type == "entry" && param.Items != nil && param.Items.Type != "string"
}
-
-func appendSimpleAssignment(param *properties.SpecParam, objectType string, builder *strings.Builder) {
- builder.WriteString(fmt.Sprintf("%s.%s = o.%s", objectType, param.Name.CamelCase, param.Name.CamelCase))
-}
-
-func appendFunctionAssignment(param *properties.SpecParam, objectType string, functionName, additionalArguments string, builder *strings.Builder) {
- if additionalArguments != "" {
- builder.WriteString(fmt.Sprintf("%s.%s = %s(o.%s, %s)", objectType, param.Name.CamelCase, functionName, param.Name.CamelCase, additionalArguments))
- } else {
- builder.WriteString(fmt.Sprintf("%s.%s = %s(o.%s)", objectType, param.Name.CamelCase, functionName, param.Name.CamelCase))
- }
-}
-
-func appendSpecObjectAssignment(param, parentParam *properties.SpecParam, objectType string, version *version.Version, listFunction, entryFunction, boolFunction, prefix, suffix string, builder *strings.Builder, isNestedListHack bool) {
- defineNestedObject([]*properties.SpecParam{param}, param, parentParam, objectType, version, listFunction, entryFunction, boolFunction, prefix, suffix, builder)
-
- if parentParam == nil && param.Type == "list" && param.Items.Type == "entry" {
- builder.WriteString(fmt.Sprintf("%s.%s = nested%sCol\n", objectType, param.Name.CamelCase, param.Name.CamelCase))
- } else {
- builder.WriteString(fmt.Sprintf("%s.%s = nested%s\n", objectType, param.Name.CamelCase, param.Name.CamelCase))
- }
-
- if isNestedListHack {
- builder.WriteString("}\n")
- }
-}
-
-func defineNestedObject(parent []*properties.SpecParam, param, parentParam *properties.SpecParam, objectType string, version *version.Version, listFunction, entryFunction, boolFunction, prefix, suffix string, builder *strings.Builder) {
-
- var isNestedListHack bool
- if parentParam == nil && param.Type == "list" && param.Items.Type == "entry" {
- isNestedListHack = true
- }
-
- declareRootOfNestedObject(parent, builder, version, prefix, suffix, isNestedListHack)
-
- if ParamSupportedInVersion(param, version) {
- startIfBlockForParamNotNil(parent, param, parentParam, builder)
-
- switch {
- case param.Spec != nil:
- assignEmptyStructForNestedObject(parent, builder, param, objectType, version, prefix, suffix)
- defineNestedObjectForChildParams(parent, param.Spec.SortedParams(), param, objectType, version, listFunction, entryFunction, boolFunction, prefix, suffix, builder)
- defineNestedObjectForChildParams(parent, param.Spec.SortedOneOf(), param, objectType, version, listFunction, entryFunction, boolFunction, prefix, suffix, builder)
- case isParamListAndProfileTypeIsMember(param):
- assignFunctionForNestedObject(parent, listFunction, "", builder, param, parentParam)
- case isParamListAndProfileTypeIsSingleEntry(param):
- assignFunctionForNestedObject(parent, entryFunction, "", builder, param, parentParam)
- case param.Type == "bool":
- assignFunctionForNestedObject(parent, boolFunction,
- useBoolFunctionForAdditionalArguments(suffix, param), builder, param, parentParam)
- default:
- assignValueForNestedObject(parent, builder, param, parentParam)
- }
-
- finishNestedObjectIfBlock(parent, param, builder)
- }
-}
-
-func startIfBlockForParamNotNil(parents []*properties.SpecParam, param *properties.SpecParam, parentParam *properties.SpecParam, builder *strings.Builder) {
- grandparent := parents[0]
-
- if grandparent != param && grandparent.Type == "list" && grandparent.Items.Type == "entry" {
- if isParamName(param) {
- builder.WriteString(fmt.Sprintf("if o%s != \"\" {\n",
- renderNestedVariableName(parents, true, true, false)))
- } else {
- builder.WriteString(fmt.Sprintf("if o%s != nil {\n",
- renderNestedVariableName(parents, true, true, false)))
- }
- } else {
- if isParamName(param) {
- builder.WriteString(fmt.Sprintf("if o%s != \"\" {\n",
- renderNestedVariableName(parents, true, true, true)))
- } else {
- builder.WriteString(fmt.Sprintf("if o%s != nil {\n",
- renderNestedVariableName(parents, true, true, true)))
- }
- }
-
-}
-
-func finishNestedObjectIfBlock(parent []*properties.SpecParam, param *properties.SpecParam, builder *strings.Builder) {
- if len(parent) == 1 && parent[0].Type == "list" && parent[0].Items.Type == "entry" {
- if isParamListAndProfileTypeIsExtendedEntry(param) {
- builder.WriteString(fmt.Sprintf("nested%sCol = append(nested%sCol, nested%s)\n",
- renderNestedVariableName(parent, true, true, false),
- renderNestedVariableName(parent, true, true, false),
- renderNestedVariableName(parent, false, false, false)))
- }
- } else {
- if isParamListAndProfileTypeIsExtendedEntry(param) {
- builder.WriteString(fmt.Sprintf("nested%s = append(nested%s, nested%s)\n",
- renderNestedVariableName(parent, true, true, false),
- renderNestedVariableName(parent, true, true, false),
- renderNestedVariableName(parent, false, false, false)))
- }
- }
-
- builder.WriteString("}\n")
-}
-
-func isParamName(param *properties.SpecParam) bool {
- return param.Required && param.Name.CamelCase == "Name"
-}
-
-func declareRootOfNestedObject(parent []*properties.SpecParam, builder *strings.Builder, version *version.Version, prefix, suffix string, isNestedListHack bool) {
- var vstr string
- if suffix != "" {
- vstr = CreateGoSuffixFromVersion(version)
- }
- if isNestedListHack {
- builder.WriteString(fmt.Sprintf("var nested%sCol []%s%s%s%s\n",
- renderNestedVariableName(parent, true, true, false), prefix,
- renderNestedVariableName(parent, false, false, false), suffix,
- vstr))
- } else if len(parent) == 1 {
- builder.WriteString(fmt.Sprintf("var nested%s *%s%s%s%s\n",
- renderNestedVariableName(parent, true, true, false), prefix,
- renderNestedVariableName(parent, false, false, false), suffix,
- vstr))
- }
-}
-
-func assignEmptyStructForNestedObject(parent []*properties.SpecParam, builder *strings.Builder, param *properties.SpecParam, objectType string, version *version.Version, prefix, suffix string) {
- if isParamListAndProfileTypeIsExtendedEntry(param) {
- createListAndLoopForNestedEntry(parent, param, builder, prefix, suffix, version)
- miscForUnknownXmlWithExtendedEntry(parent, objectType, builder, suffix)
- } else {
- createStructForParamWithSpec(parent, builder, prefix, suffix, version)
- miscForUnknownXmlWithSpec(parent, builder, suffix, objectType)
- }
- builder.WriteString("}\n")
-}
-
-func createStructForParamWithSpec(parent []*properties.SpecParam, builder *strings.Builder, prefix string, suffix string, version *version.Version) {
- var vstr string
- if suffix != "" {
- vstr = CreateGoSuffixFromVersion(version)
- }
- builder.WriteString(fmt.Sprintf("nested%s = &%s%s%s%s{}\n",
- renderNestedVariableName(parent, true, true, false), prefix,
- renderNestedVariableName(parent, false, false, false), suffix,
- vstr))
-}
-
-func createListAndLoopForNestedEntry(parent []*properties.SpecParam, param *properties.SpecParam, builder *strings.Builder, prefix string, suffix string, version *version.Version) {
- var vstr string
- if suffix != "" {
- vstr = CreateGoSuffixFromVersion(version)
- }
-
- if len(parent) == 1 && parent[0].Type == "list" && parent[0].Items.Type == "entry" {
- builder.WriteString(fmt.Sprintf("nested%sCol = []%s%s%s%s{}\n",
- renderNestedVariableName(parent, true, true, false), prefix,
- renderNestedVariableName(parent, false, false, false), suffix,
- vstr))
- } else {
- builder.WriteString(fmt.Sprintf("nested%s = []%s%s%s%s{}\n",
- renderNestedVariableName(parent, true, true, false), prefix,
- renderNestedVariableName(parent, false, false, false), suffix,
- vstr))
- }
-
- startFromDot := true
- if len(parent) >= 2 && parent[0].Type == "list" && parent[0].Items.Type == "entry" {
- startFromDot = false
- }
-
- builder.WriteString(fmt.Sprintf("for _, o%s := range o%s { \n",
- renderNestedVariableName(parent, false, false, false),
- renderNestedVariableName(parent, true, true, startFromDot)))
- builder.WriteString(fmt.Sprintf("nested%s := %s%s%s%s{}\n",
- renderNestedVariableName(parent, false, false, false),
- prefix, renderNestedVariableName(parent, false, false, false), suffix,
- vstr))
-}
-
-func miscForUnknownXmlWithSpec(parent []*properties.SpecParam, builder *strings.Builder, suffix string, objectType string) {
- if suffix == "Xml" {
- builder.WriteString(fmt.Sprintf("if _, ok := o.Misc[\"%s\"]; ok {\n",
- renderNestedVariableName(parent, false, false, false)))
- builder.WriteString(fmt.Sprintf("nested%s.Misc = o.Misc[\"%s\"]\n",
- renderNestedVariableName(parent, true, true, false),
- renderNestedVariableName(parent, false, false, false),
- ))
- } else {
- startsWithDot := true
- if parent[0].Type == "list" && parent[0].Items.Type == "entry" {
- startsWithDot = false
- }
-
- builder.WriteString(fmt.Sprintf("if o%s.Misc != nil {\n",
- renderNestedVariableName(parent, true, true, startsWithDot)))
- builder.WriteString(fmt.Sprintf("%s.Misc[\"%s\"] = o%s.Misc\n",
- objectType, renderNestedVariableName(parent, false, false, false),
- renderNestedVariableName(parent, true, true, startsWithDot),
- ))
- }
-}
-
-func miscForUnknownXmlWithExtendedEntry(parent []*properties.SpecParam, objectType string, builder *strings.Builder, suffix string) {
- if suffix == "Xml" {
- builder.WriteString(fmt.Sprintf("if _, ok := o.Misc[\"%s\"]; ok {\n",
- renderNestedVariableName(parent, false, false, false)))
- builder.WriteString(fmt.Sprintf("nested%s.Misc = o.Misc[\"%s\"]\n",
- renderNestedVariableName(parent, false, false, false),
- renderNestedVariableName(parent, false, false, false),
- ))
- } else {
- builder.WriteString(fmt.Sprintf("if o%s.Misc != nil {\n",
- renderNestedVariableName(parent, false, false, false)))
- builder.WriteString(fmt.Sprintf("%s.Misc[\"%s\"] = o%s.Misc\n",
- objectType,
- renderNestedVariableName(parent, false, false, false),
- renderNestedVariableName(parent, false, false, false),
- ))
- }
-}
-
-var _ = log.Printf
-
-func assignValueForNestedObject(parent []*properties.SpecParam, builder *strings.Builder, param, parentParam *properties.SpecParam) {
- if parent[0] != param && parent[0].Type == "list" && parent[0].Items.Type == "entry" {
- builder.WriteString(fmt.Sprintf("nested%s = o%s\n",
- renderNestedVariableName(parent, true, true, false),
- renderNestedVariableName(parent, true, true, false)))
- } else {
- builder.WriteString(fmt.Sprintf("nested%s = o%s\n",
- renderNestedVariableName(parent, true, true, false),
- renderNestedVariableName(parent, true, true, true)))
- }
-}
-
-func assignFunctionForNestedObject(parent []*properties.SpecParam, functionName, additionalArguments string, builder *strings.Builder, param, parentParam *properties.SpecParam) {
-
- var startWithDot bool
- if parent[0] != param && parent[0].Type == "list" && parent[0].Items.Type == "entry" {
- startWithDot = false
- } else {
- startWithDot = true
- }
- if additionalArguments != "" {
- builder.WriteString(fmt.Sprintf("nested%s = %s(o%s, %s)\n",
- renderNestedVariableName(parent, true, true, false), functionName,
- renderNestedVariableName(parent, true, true, startWithDot), additionalArguments))
- } else {
- builder.WriteString(fmt.Sprintf("nested%s = %s(o%s)\n",
- renderNestedVariableName(parent, true, true, false), functionName,
- renderNestedVariableName(parent, true, true, startWithDot)))
- }
-}
-
-func defineNestedObjectForChildParams(parent []*properties.SpecParam, params []*properties.SpecParam, parentParam *properties.SpecParam, objectType string, version *version.Version, listFunction, entryFunction, boolFunction, prefix, suffix string, builder *strings.Builder) {
- for _, param := range params {
- defineNestedObject(append(parent, param), param, parentParam, objectType, version, listFunction, entryFunction, boolFunction, prefix, suffix, builder)
- if isParamListAndProfileTypeIsExtendedEntry(param) {
- builder.WriteString("}\n")
- }
- }
-}
-
-func renderNestedVariableName(params []*properties.SpecParam, useDot, searchForParamWithEntry, startFromDot bool) string {
- var builder strings.Builder
-
- indexOfLastParamWithExtendedEntry := 0
-
- if searchForParamWithEntry && len(params) > 2 {
- for i := len(params) - 2; i >= 0; i-- {
- if isParamListAndProfileTypeIsExtendedEntry(params[i]) {
- indexOfLastParamWithExtendedEntry = i
- break
- }
- }
- }
-
- for i, param := range params {
- if useDot && startFromDot && i == 0 && (!searchForParamWithEntry ||
- searchForParamWithEntry && i >= indexOfLastParamWithExtendedEntry) {
- builder.WriteString(".")
- }
- builder.WriteString(param.Name.CamelCase)
- if useDot && i < len(params)-1 && (!searchForParamWithEntry ||
- searchForParamWithEntry && i >= indexOfLastParamWithExtendedEntry) {
- builder.WriteString(".")
- }
- }
-
- return builder.String()
-}
diff --git a/pkg/translate/assignments_test.go b/pkg/translate/assignments_test.go
deleted file mode 100644
index 3a4c0d62..00000000
--- a/pkg/translate/assignments_test.go
+++ /dev/null
@@ -1,298 +0,0 @@
-package translate
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-
- "github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
-)
-
-func TestSpecifyEntryAssignmentForFlatStructure(t *testing.T) {
- // given
- paramTypeString := properties.SpecParam{
- Name: &properties.NameVariant{
- CamelCase: "Description",
- Underscore: "description",
- },
- Profiles: []*properties.SpecParamProfile{
- {
- Type: "string",
- Xpath: []string{"description"},
- },
- },
- }
- paramTypeListString := properties.SpecParam{
- Type: "list",
- Name: &properties.NameVariant{
- CamelCase: "Tags",
- Underscore: "tags",
- },
- Profiles: []*properties.SpecParamProfile{
- {
- Type: "member",
- Xpath: []string{"tags"},
- },
- },
- }
-
- // when
- calculatedAssignmentString := SpecifyEntryAssignment("entry", ¶mTypeString, nil)
- calculatedAssignmentListString := SpecifyEntryAssignment("entry", ¶mTypeListString, nil)
-
- // then
- assert.Equal(t, "entry.Description = o.Description", calculatedAssignmentString)
- assert.Equal(t, "entry.Tags = util.StrToMem(o.Tags)", calculatedAssignmentListString)
-}
-
-func TestSpecifyEntryAssignmentForNestedObject(t *testing.T) {
- // given
- spec := properties.Spec{
- Params: map[string]*properties.SpecParam{
- "a": {
- Name: &properties.NameVariant{
- Underscore: "a",
- CamelCase: "A",
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "b": {
- Name: &properties.NameVariant{
- Underscore: "b",
- CamelCase: "B",
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "c": {
- Name: &properties.NameVariant{
- Underscore: "c",
- CamelCase: "C",
- },
- },
- },
- },
- },
- },
- },
- },
- },
- }
- expectedAssignmentString := `var nestedA *AXml
-if o.A != nil {
-nestedA = &AXml{}
-if _, ok := o.Misc["A"]; ok {
-nestedA.Misc = o.Misc["A"]
-}
-if o.A.B != nil {
-nestedA.B = &ABXml{}
-if _, ok := o.Misc["AB"]; ok {
-nestedA.B.Misc = o.Misc["AB"]
-}
-if o.A.B.C != nil {
-nestedA.B.C = o.A.B.C
-}
-}
-}
-entry.A = nestedA
-`
- // when
- calculatedAssignmentString := SpecifyEntryAssignment("entry", spec.Params["a"], nil)
-
- // then
- assert.Equal(t, expectedAssignmentString, calculatedAssignmentString)
-}
-
-func TestNormalizeAssignmentForNestedObject(t *testing.T) {
- // given
- spec := properties.Spec{
- Params: map[string]*properties.SpecParam{
- "a": {
- Name: &properties.NameVariant{
- Underscore: "a",
- CamelCase: "A",
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "b": {
- Name: &properties.NameVariant{
- Underscore: "b",
- CamelCase: "B",
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "c": {
- Name: &properties.NameVariant{
- Underscore: "c",
- CamelCase: "C",
- },
- },
- },
- },
- },
- },
- },
- },
- },
- }
- expectedAssignmentString := `var nestedA *A
-if o.A != nil {
-nestedA = &A{}
-if o.A.Misc != nil {
-entry.Misc["A"] = o.A.Misc
-}
-if o.A.B != nil {
-nestedA.B = &AB{}
-if o.A.B.Misc != nil {
-entry.Misc["AB"] = o.A.B.Misc
-}
-if o.A.B.C != nil {
-nestedA.B.C = o.A.B.C
-}
-}
-}
-entry.A = nestedA
-`
- // when
- calculatedAssignmentString := NormalizeAssignment("entry", spec.Params["a"], nil)
-
- // then
- assert.Equal(t, expectedAssignmentString, calculatedAssignmentString)
-}
-
-func TestPrepareAssignment(t *testing.T) {
- // given
- objectType := "entry"
- param := &properties.SpecParam{
- Name: &properties.NameVariant{
- CamelCase: "Description",
- Underscore: "description",
- },
- Type: "list",
- Items: &properties.SpecParamItems{
- Type: "string",
- },
- Profiles: []*properties.SpecParamProfile{
- {
- Type: "member",
- Xpath: []string{"description"},
- },
- },
- }
- listFunction := "util.StrToMem"
- entryFunction := ""
- boolFunction := "util.Bool"
- prefix := ""
- suffix := "Xml"
-
- expectedAssignment := `entry.Description = util.StrToMem(o.Description)`
-
- // when
- calculatedAssignment := prepareAssignment(objectType, param, listFunction, entryFunction, boolFunction, prefix, suffix, nil)
-
- // then
- assert.Equal(t, expectedAssignment, calculatedAssignment)
-}
-
-func TestNestedVariableNameWithoutEntry(t *testing.T) {
- // given
- spec := properties.Spec{
- Params: map[string]*properties.SpecParam{
- "a": {
- Name: &properties.NameVariant{
- Underscore: "a",
- CamelCase: "A",
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "b": {
- Name: &properties.NameVariant{
- Underscore: "b",
- CamelCase: "B",
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "c": {
- Name: &properties.NameVariant{
- Underscore: "c",
- CamelCase: "C",
- },
- },
- },
- },
- },
- },
- },
- },
- },
- }
- expectedNestedVariableName := `A.B.C`
- params := []*properties.SpecParam{}
- params = append(params,
- spec.Params["a"],
- spec.Params["a"].Spec.Params["b"],
- spec.Params["a"].Spec.Params["b"].Spec.Params["c"],
- )
-
- // when
- calculatedNestedVariableName := renderNestedVariableName(params, true, true, false)
-
- // then
- assert.Equal(t, expectedNestedVariableName, calculatedNestedVariableName)
-}
-
-func TestNestedVariableNameWithEntry(t *testing.T) {
- // given
- spec := properties.Spec{
- Params: map[string]*properties.SpecParam{
- "a": {
- Name: &properties.NameVariant{
- Underscore: "a",
- CamelCase: "A",
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "b": {
- Name: &properties.NameVariant{
- Underscore: "b",
- CamelCase: "B",
- },
- Type: "list",
- Items: &properties.SpecParamItems{
- Type: "entry",
- },
- Profiles: []*properties.SpecParamProfile{
- {
- Xpath: []string{"test", "entry"},
- Type: "entry",
- },
- },
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "c": {
- Name: &properties.NameVariant{
- Underscore: "c",
- CamelCase: "C",
- },
- },
- },
- },
- },
- },
- },
- },
- },
- }
- expectedNestedVariableName := `AB.C`
- params := []*properties.SpecParam{}
- params = append(params,
- spec.Params["a"],
- spec.Params["a"].Spec.Params["b"],
- spec.Params["a"].Spec.Params["b"].Spec.Params["c"],
- )
-
- // when
- calculatedNestedVariableName := renderNestedVariableName(params, true, true, false)
-
- // then
- assert.Equal(t, expectedNestedVariableName, calculatedNestedVariableName)
-}
diff --git a/pkg/translate/funcs_test.go b/pkg/translate/funcs_test.go
index cabccc0a..6310a2c5 100644
--- a/pkg/translate/funcs_test.go
+++ b/pkg/translate/funcs_test.go
@@ -12,10 +12,10 @@ func TestGenerateEntryXpath(t *testing.T) {
// given
// when
- asEntryXpath, _ := GenerateEntryXpath("util.AsEntryXpath([]string{", "})", "DeviceGroup", "{{ Entry $panorama_device }}")
+ asEntryXpath, _ := GenerateEntryXpath("util.AsEntryXpath(", ")", "DeviceGroup", "{{ Entry $panorama_device }}")
// then
- assert.Equal(t, "util.AsEntryXpath([]string{o.DeviceGroup.PanoramaDevice}),", asEntryXpath)
+ assert.Equal(t, "util.AsEntryXpath(o.DeviceGroup.PanoramaDevice),", asEntryXpath)
}
func TestSpecMatchesFunction(t *testing.T) {
diff --git a/pkg/translate/imports.go b/pkg/translate/imports.go
index f6932929..8e854052 100644
--- a/pkg/translate/imports.go
+++ b/pkg/translate/imports.go
@@ -2,10 +2,11 @@ package translate
import (
"github.com/paloaltonetworks/pan-os-codegen/pkg/imports"
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
)
// RenderImports render string, which contains import required in entry, location or service template.
-func RenderImports(templateTypes ...string) (string, error) {
+func RenderImports(spec *properties.Normalization, templateTypes ...string) (string, error) {
manager := imports.NewManager()
for _, templateType := range templateTypes {
@@ -30,6 +31,9 @@ func RenderImports(templateTypes ...string) (string, error) {
manager.AddSdkImport("github.com/PaloAltoNetworks/pango/errors", "")
manager.AddSdkImport("github.com/PaloAltoNetworks/pango/util", "")
manager.AddSdkImport("github.com/PaloAltoNetworks/pango/version", "")
+ if spec.ResourceXpathVariablesWithChecks(true) {
+ manager.AddStandardImport("strings", "")
+ }
case "service":
manager.AddStandardImport("context", "")
manager.AddStandardImport("fmt", "")
diff --git a/pkg/translate/imports_test.go b/pkg/translate/imports_test.go
index caf28de4..f9f81e1b 100644
--- a/pkg/translate/imports_test.go
+++ b/pkg/translate/imports_test.go
@@ -4,6 +4,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
+
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
)
func TestRenderImports(t *testing.T) {
@@ -18,7 +20,13 @@ import (
)`
// when
- actualImports, _ := RenderImports("location")
+ spec := &properties.Normalization{
+ PanosXpath: properties.PanosXpath{
+ Path: []string{"test"},
+ },
+ }
+
+ actualImports, _ := RenderImports(spec, "location")
// then
assert.NotNil(t, actualImports)
diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go
index 21602424..1c584d97 100644
--- a/pkg/translate/structs.go
+++ b/pkg/translate/structs.go
@@ -12,6 +12,20 @@ import (
"github.com/paloaltonetworks/pan-os-codegen/pkg/version"
)
+type structType string
+
+const (
+ structXmlType structType = "xml"
+ structApiType structType = "api"
+)
+
+var xmlNameVariant = &properties.NameVariant{
+ Original: "xml-name",
+ LowerCamelCase: "xmlName",
+ CamelCase: "XMLName",
+ Underscore: "xml_name",
+}
+
// LocationType function used in template location.tmpl to generate location type name.
func LocationType(location *properties.Location, pointer bool) string {
prefix := ""
@@ -21,85 +35,6 @@ func LocationType(location *properties.Location, pointer bool) string {
return fmt.Sprintf("%s%sLocation", prefix, location.Name.CamelCase)
}
-// NestedSpecs goes through all params and one ofs (recursively) and returns map of all nested specs.
-func NestedSpecs(spec *properties.Spec) (map[string]NestedSpec, error) {
- nestedSpecs := make(map[string]NestedSpec)
-
- fmt.Println("HELLO1")
- if spec == nil {
- panic("spec == nil")
- }
-
- checkNestedSpecs([]string{}, spec, nestedSpecs)
- fmt.Println("END1")
-
- return nestedSpecs, nil
-}
-
-type NestedSpec struct {
- ParentIsList bool
- Spec *properties.Spec
-}
-
-func checkNestedSpecs(parent []string, spec *properties.Spec, nestedSpecs map[string]NestedSpec) {
- for _, param := range spec.SortedParams() {
- paramKey := append(parent, param.Name.CamelCase)
- updateNestedSpecs(paramKey, param, nestedSpecs)
- if len(param.Profiles) > 0 && param.Profiles[0].Type == "entry" && param.Items != nil && param.Items.Type == "entry" {
- nested, modified := addNameAsParamForNestedSpec(paramKey, nestedSpecs)
- nested.ParentIsList = true
- if modified {
- nested.Spec.HackFixInjectedNameSpecOrder()
- }
- }
- }
- for _, param := range spec.SortedOneOf() {
- paramKey := append(parent, param.Name.CamelCase)
- updateNestedSpecs(paramKey, param, nestedSpecs)
- if len(param.Profiles) > 0 && param.Profiles[0].Type == "entry" && param.Items != nil && param.Items.Type == "entry" {
- nested, modified := addNameAsParamForNestedSpec(paramKey, nestedSpecs)
- nested.ParentIsList = true
- if modified {
- nested.Spec.HackFixInjectedNameSpecOrder()
- }
- }
- }
-}
-
-func updateNestedSpecs(parent []string, param *properties.SpecParam, nestedSpecs map[string]NestedSpec) {
- if param.Spec != nil {
- nestedSpecs[strings.Join(parent, "")] = NestedSpec{
- Spec: param.Spec,
- }
-
- checkNestedSpecs(parent, param.Spec, nestedSpecs)
- }
-}
-
-func addNameAsParamForNestedSpec(parent []string, nestedSpecs map[string]NestedSpec) (*NestedSpec, bool) {
- nested := nestedSpecs[strings.Join(parent, "")]
- if _, found := nested.Spec.Params["name"]; found {
- return &nested, false
- }
-
- nested.Spec.Params["name"] = &properties.SpecParam{
- Name: &properties.NameVariant{
- Underscore: "name",
- CamelCase: "Name",
- },
- SpecOrder: 0,
- Type: "string",
- Required: true,
- Profiles: []*properties.SpecParamProfile{
- {
- Xpath: []string{"name"},
- },
- },
- }
-
- return &nested, true
-}
-
const importLocationStructTmpl = `
type ImportLocation interface {
XpathForLocation(version.Number, util.ILocation) ([]string, error)
@@ -301,7 +236,7 @@ func createImportLocationSpecsForLocation(location properties.ImportLocation) im
for _, elt := range location.XpathElements {
if strings.HasPrefix(elt, "$") {
variableName := elt[1:]
- asEntryXpath := fmt.Sprintf("util.AsEntryXpath([]string{o.%s})", variablesByName[variableName].Name.LowerCamelCase)
+ asEntryXpath := fmt.Sprintf("util.AsEntryXpath(o.%s)", variablesByName[variableName].Name.LowerCamelCase)
elements = append(elements, asEntryXpath)
} else {
elements = append(elements, fmt.Sprintf("\"%s\"", elt))
@@ -378,24 +313,39 @@ func SpecParamType(parent string, param *properties.SpecParam) string {
return fmt.Sprintf("%s%s", prefix, calculatedType)
}
-// XmlParamType return param type (it can be nested spec) (for struct based on spec from YAML files).
-func XmlParamType(parent string, param *properties.SpecParam) string {
- prefix := determinePrefix(param, true)
-
- calculatedType := ""
- if param.Spec != nil {
- calculatedType = calculateNestedXmlSpecType(parent, param)
+// ParamType return param type (it can be nested spec) (for struct based on spec from YAML files).
+func ParamType(structTyp structType, parentName *properties.NameVariant, param *properties.SpecParam, suffix string) string {
+ var calculatedType string
+ if param.Type == "" || isParamListAndProfileTypeIsExtendedEntry(param) {
+ typ := calculateNestedXmlSpecType(structTyp, parentName, param, suffix)
+ if structTyp == structXmlType {
+ calculatedType = typ.LowerCamelCase
+ } else {
+ calculatedType = typ.CamelCase
+ }
} else if isParamListAndProfileTypeIsMember(param) {
- calculatedType = "util.MemberType"
+ if structTyp == structXmlType {
+ calculatedType = "util.Member"
+ } else {
+ calculatedType = "string"
+ }
} else if isParamListAndProfileTypeIsSingleEntry(param) {
- calculatedType = "util.EntryType"
- } else if param.Type == "bool" {
+ if structTyp == structXmlType {
+ calculatedType = "util.Entry"
+ } else {
+ calculatedType = calculateNestedXmlSpecType(structTyp, parentName, param, suffix).CamelCase
+ }
+ } else if param.Type == "bool" && structTyp == structXmlType {
calculatedType = "string"
} else {
calculatedType = param.Type
}
- return fmt.Sprintf("%s%s", prefix, calculatedType)
+ return calculatedType
+}
+
+func XmlParamType(parent string, param *properties.SpecParam) string {
+ return ParamType(structXmlType, properties.NewNameVariant(parent), param, "")
}
func determinePrefix(param *properties.SpecParam, useMemberOrEntryTypeStruct bool) string {
@@ -422,13 +372,28 @@ func calculateNestedSpecType(parent string, param *properties.SpecParam) string
return fmt.Sprintf("%s%s", parent, naming.CamelCase("", param.Name.CamelCase, "", true))
}
-func calculateNestedXmlSpecType(parent string, param *properties.SpecParam) string {
- return fmt.Sprintf("%s%sXml", parent, naming.CamelCase("", param.Name.CamelCase, "", true))
+func calculateNestedXmlSpecType(structTyp structType, parentName *properties.NameVariant, param *properties.SpecParam, suffix string) *properties.NameVariant {
+ var typ *properties.NameVariant
+ if parentName.IsEmpty() {
+ typ = param.Name
+ } else {
+ typ = parentName.WithSuffix(param.Name)
+ }
+
+ if structTyp == structXmlType {
+ typ = typ.WithSuffix(properties.NewNameVariant("xml")).WithLiteralSuffix(suffix)
+ }
+
+ return typ
}
// XmlName creates a string with xml name (e.g. `description`).
func XmlName(param *properties.SpecParam) string {
if len(param.Profiles) > 0 {
+ // FIXME: lists of objects have an extra "entry" element on their xpath
+ if param.Type == "list" && param.Items.Type == "entry" {
+ return param.Profiles[0].Xpath[0]
+ }
return strings.Join(param.Profiles[0].Xpath, ">")
}
@@ -484,6 +449,14 @@ func CreateGoSuffixFromVersion(v *version.Version) string {
return fmt.Sprintf("_%s", strings.ReplaceAll(v.String(), ".", "_"))
}
+func ParamNotSkippedTmpl(param *properties.SpecParam) bool {
+ if param.GoSdkConfig != nil && param.GoSdkConfig.Skip != nil {
+ return !*param.GoSdkConfig.Skip
+ }
+
+ return true
+}
+
func ParamSupportedInVersionTmpl(param *properties.SpecParam, deviceVersion any) (bool, error) {
if deviceVersion == nil {
return true, nil
@@ -513,7 +486,7 @@ func checkIfDeviceVersionSupportedByProfile(param *properties.SpecParam, deviceV
return true
}
- log.Printf("Param: %s, Version: %s, MinVersion: %s, MaxVersion: %s", param.Name.CamelCase, deviceVersion, profile.MinVersion.String(), profile.MaxVersion.String())
+ log.Printf("Param: %s, deviceVersion: %s, MinVersion: %s, MaxVersion: %s", param.Name.CamelCase, deviceVersion, profile.MinVersion.String(), profile.MaxVersion.String())
if deviceVersion.GreaterThanOrEqualTo(*profile.MinVersion) && deviceVersion.LesserThan(*profile.MaxVersion) {
return true
@@ -521,3 +494,732 @@ func checkIfDeviceVersionSupportedByProfile(param *properties.SpecParam, deviceV
}
return false
}
+
+type entryStructFieldContext struct {
+ Name *properties.NameVariant
+ IsInternal bool
+ Required bool
+ FieldType string
+ Type string
+ ItemsType string
+ XmlType string
+ XmlContainerType string
+ ItemsXmlType string
+ Tags string
+ version *version.Version
+}
+
+func (o entryStructFieldContext) FinalType() string {
+ switch o.FieldType {
+ case "list-entry", "list-member":
+ return o.ItemsType
+ case "object", "simple":
+ if o.Required {
+ return o.Type
+ } else {
+ return "*" + o.Type
+ }
+ case "internal":
+ return o.Type
+ default:
+ panic(fmt.Sprintf("unreachable FieldType '%s' for '%s'", o.FieldType, o.Name.CamelCase))
+ }
+}
+
+func (o entryStructFieldContext) FinalXmlType() string {
+ switch o.FieldType {
+ case "list-entry":
+ if o.XmlContainerType != "" {
+ return "*" + o.XmlContainerType
+ } else {
+ return o.ItemsXmlType
+ }
+ case "list-member":
+ return "*" + o.ItemsXmlType
+ case "object", "simple":
+ if o.Required {
+ return o.XmlType
+ } else {
+ return "*" + o.XmlType
+ }
+ case "internal":
+ return o.XmlType
+ default:
+ panic(fmt.Sprintf("unreachable FieldType '%s' for '%s'", o.FieldType, o.Name.CamelCase))
+ }
+}
+
+type entryStructContext struct {
+ TopLevel bool
+ IsXmlContainer bool
+ Fields []entryStructFieldContext
+
+ version *version.Version
+ name *properties.NameVariant
+}
+
+func (o entryStructContext) versionSuffix() string {
+ if o.version == nil {
+ return ""
+ }
+
+ return fmt.Sprintf("_%s", strings.ReplaceAll(o.version.String(), ".", "_"))
+}
+
+func (o entryStructContext) StructName() string {
+ return o.name.CamelCase
+}
+
+func (o entryStructContext) XmlStructName() string {
+ return o.name.LowerCamelCase + "Xml" + o.versionSuffix()
+}
+
+func (o entryStructContext) XmlContainerStructName() string {
+ return o.name.LowerCamelCase + "XmlContainer" + o.versionSuffix()
+}
+
+func (o entryStructContext) SpecifierFuncName(suffix string) string {
+ return "specify" + suffix + o.versionSuffix()
+}
+
+func getTypesForParam(structTyp structType, parent *properties.NameVariant, param *properties.SpecParam, version *version.Version, overrideForXmlContainer bool) (string, string, string) {
+ var versionSuffix string
+ if version != nil {
+ versionSuffix = fmt.Sprintf("_%s", strings.ReplaceAll(version.String(), ".", "_"))
+ }
+
+ if structTyp == structXmlType {
+ typ := ParamType(structXmlType, parent, param, versionSuffix)
+ var itemsType string
+ if param.Type == "list" && param.Items.Type == "string" {
+ itemsType = "util.MemberType"
+ } else if param.Type == "list" && param.Items.Type == "entry" {
+ itemsType = "[]" + typ
+ }
+ var xmlContainerType string
+ if overrideForXmlContainer {
+ xmlContainerType = parent.WithSuffix(param.Name).WithSuffix(properties.NewNameVariant("container")).WithSuffix(properties.NewNameVariant("xml")).WithLiteralSuffix(versionSuffix).LowerCamelCase
+ }
+ return typ, itemsType, xmlContainerType
+ } else {
+ typ := ParamType(structApiType, parent, param, "")
+ var itemsType string
+ if param.Type == "list" && param.Items.Type == "string" {
+ itemsType = "[]string"
+ } else if param.Type == "list" && param.Items.Type == "entry" {
+ itemsType = "[]" + typ
+ }
+ return typ, itemsType, ""
+ }
+}
+
+func getFieldTypeForParam(param *properties.SpecParam) string {
+ if param.Type == "" {
+ return "object"
+ }
+
+ if param.Type == "list" && param.Items.Type == "string" {
+ return "list-member"
+ }
+
+ if param.Type == "list" && param.Items.Type == "entry" {
+ return "list-entry"
+ }
+
+ return "simple"
+}
+
+func createStructSpecForXmlListContainer(prefix *properties.NameVariant, param *properties.SpecParam, version *version.Version) []entryStructContext {
+ typ, itemsType, _ := getTypesForParam(structApiType, prefix, param, version, false)
+ xmlType, itemsXmlType, _ := getTypesForParam(structXmlType, prefix, param, version, false)
+ fieldType := "list-entry"
+
+ fields := []entryStructFieldContext{
+ {
+ Name: properties.NewNameVariant("entries"),
+ Required: false,
+ FieldType: fieldType,
+ Type: typ,
+ ItemsType: itemsType,
+ XmlType: xmlType,
+ ItemsXmlType: itemsXmlType,
+ Tags: "`xml:\"entry\"`",
+ version: version,
+ },
+ }
+
+ return []entryStructContext{{
+ IsXmlContainer: true,
+ Fields: fields,
+ name: prefix.WithSuffix(param.Name).WithSuffix(properties.NewNameVariant("container")),
+ version: version,
+ }}
+}
+
+func createEntryXmlStructSpecsForParameter(structTyp structType, parentPrefix *properties.NameVariant, param *properties.SpecParam, version *version.Version) []entryStructContext {
+ var fields []entryStructFieldContext
+ var entries []entryStructContext
+
+ if param.Type == "list" && param.Items.Type == "entry" {
+ if structTyp == structXmlType {
+ fields = append(fields, entryStructFieldContext{
+ IsInternal: true,
+ FieldType: "internal",
+ Name: xmlNameVariant,
+ XmlType: "xml.Name",
+ Tags: "`xml:\"entry\"`",
+ })
+ }
+ fields = append(fields, entryStructFieldContext{
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ })
+ }
+
+ processParameter := func(prefix *properties.NameVariant, param *properties.SpecParam) {
+ if param.GoSdkConfig != nil && param.GoSdkConfig.Skip != nil && *param.GoSdkConfig.Skip {
+ return
+ }
+
+ if !ParamSupportedInVersion(param, version) {
+ return
+ }
+
+ var overrideTypeForXmlContainer bool
+ if structTyp == structXmlType && param.Type == "list" && param.Items.Type == "entry" {
+ overrideTypeForXmlContainer = true
+ entries = append(entries, createStructSpecForXmlListContainer(prefix, param, version)...)
+ }
+
+ typ, itemsType, _ := getTypesForParam(structApiType, prefix, param, version, overrideTypeForXmlContainer)
+ xmlType, itemsXmlType, xmlContainerType := getTypesForParam(structXmlType, prefix, param, version, overrideTypeForXmlContainer)
+ fieldType := getFieldTypeForParam(param)
+
+ fields = append(fields, entryStructFieldContext{
+ Name: param.Name,
+ Required: param.Required,
+ FieldType: fieldType,
+ Type: typ,
+ ItemsType: itemsType,
+ XmlType: xmlType,
+ XmlContainerType: xmlContainerType,
+ ItemsXmlType: itemsXmlType,
+ Tags: XmlTag(param),
+ version: version,
+ })
+
+ if param.Type == "" || (param.Type == "list" && param.Items.Type == "entry") {
+ entries = append(entries, createEntryXmlStructSpecsForParameter(structTyp, prefix, param, version)...)
+ }
+
+ }
+
+ prefixName := parentPrefix.WithSuffix(param.Name)
+ for _, elt := range param.Spec.SortedParams() {
+ processParameter(prefixName, elt)
+ }
+
+ for _, elt := range param.Spec.SortedOneOf() {
+ processParameter(prefixName, elt)
+ }
+
+ fields = append(fields, entryStructFieldContext{
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ })
+
+ name := parentPrefix.WithSuffix(param.Name)
+ entries = append([]entryStructContext{{
+ Fields: fields,
+ name: name,
+ version: version,
+ }}, entries...)
+
+ return entries
+}
+
+func creasteStructSpecsForNormalization(structTyp structType, parentPrefix *properties.NameVariant, spec *properties.Normalization, version *version.Version) []entryStructContext {
+ var entries []entryStructContext
+ var fields []entryStructFieldContext
+
+ if structTyp == structXmlType {
+ var xmlTags string
+ switch spec.TerraformProviderConfig.ResourceType {
+ case properties.TerraformResourceEntry, properties.TerraformResourceUuid:
+ xmlTags = "`xml:\"entry\"`"
+ case properties.TerraformResourceConfig:
+ xmlTags = "`xml:\"system\"`"
+ case properties.TerraformResourceCustom:
+ fallthrough
+ default:
+ panic(fmt.Sprintf("unreachable resource type: '%s'", spec.TerraformProviderConfig.ResourceType))
+ }
+
+ fields = append(fields, entryStructFieldContext{
+ IsInternal: true,
+ FieldType: "internal",
+ Name: xmlNameVariant,
+ XmlType: "xml.Name",
+ Tags: xmlTags,
+ })
+ }
+
+ switch spec.TerraformProviderConfig.ResourceType {
+ case properties.TerraformResourceEntry, properties.TerraformResourceUuid:
+ fields = append(fields, entryStructFieldContext{
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ })
+ case properties.TerraformResourceConfig:
+ case properties.TerraformResourceCustom:
+ fallthrough
+ default:
+ panic(fmt.Sprintf("unreachable resource type: '%s'", spec.TerraformProviderConfig.ResourceType))
+ }
+
+ processParameter := func(prefix *properties.NameVariant, param *properties.SpecParam) {
+ if param.GoSdkConfig != nil && param.GoSdkConfig.Skip != nil && *param.GoSdkConfig.Skip {
+ return
+ }
+
+ if !ParamSupportedInVersion(param, version) {
+ return
+ }
+
+ var overrideTypeForXmlContainer bool
+ if structTyp == structXmlType && param.Type == "list" && param.Items.Type == "entry" {
+ overrideTypeForXmlContainer = true
+ entries = append(entries, createStructSpecForXmlListContainer(prefix, param, version)...)
+ }
+
+ typ, itemsType, _ := getTypesForParam(structApiType, prefix, param, version, overrideTypeForXmlContainer)
+ xmlType, itemsXmlType, xmlContainerType := getTypesForParam(structXmlType, prefix, param, version, overrideTypeForXmlContainer)
+ fieldType := getFieldTypeForParam(param)
+
+ fields = append(fields, entryStructFieldContext{
+ Name: param.Name,
+ Required: param.Required,
+ FieldType: fieldType,
+ Type: typ,
+ ItemsType: itemsType,
+ XmlType: xmlType,
+ XmlContainerType: xmlContainerType,
+ ItemsXmlType: itemsXmlType,
+ Tags: XmlTag(param),
+ version: version,
+ })
+
+ if param.Type == "" || (param.Type == "list" && param.Items.Type == "entry") {
+ entries = append(entries, createEntryXmlStructSpecsForParameter(structTyp, properties.NewNameVariant(""), param, version)...)
+ }
+ }
+
+ for _, elt := range spec.Spec.SortedParams() {
+ processParameter(parentPrefix, elt)
+ }
+
+ for _, elt := range spec.Spec.SortedOneOf() {
+ processParameter(parentPrefix, elt)
+ }
+
+ fields = append(fields, entryStructFieldContext{
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ })
+
+ var name *properties.NameVariant
+ switch spec.TerraformProviderConfig.ResourceType {
+ case properties.TerraformResourceEntry, properties.TerraformResourceUuid:
+ name = properties.NewNameVariant("entry")
+ case properties.TerraformResourceConfig:
+ name = properties.NewNameVariant("config")
+ case properties.TerraformResourceCustom:
+ fallthrough
+ default:
+ panic(fmt.Sprintf("unreachable resource type: %v", spec.TerraformProviderConfig.ResourceType))
+ }
+
+ entries = append([]entryStructContext{{
+ TopLevel: true,
+ Fields: fields,
+ name: name,
+ version: version,
+ }}, entries...)
+
+ return entries
+}
+
+func createStructSpecs(structTyp structType, spec *properties.Normalization, version *version.Version) []entryStructContext {
+ return creasteStructSpecsForNormalization(structTyp, properties.NewNameVariant(""), spec, version)
+}
+
+const apiStructsTmpl = `
+{{- range .Specs }}
+{{- $spec := . }}
+type {{ .StructName }} struct{
+ {{- range .Fields }}
+ {{- if .IsInternal }}{{ continue }}{{ end }}
+ {{ .Name.CamelCase }} {{ .FinalType }}
+ {{- end }}
+}
+{{- end }}
+`
+
+func RenderEntryApiStructs(spec *properties.Normalization) (string, error) {
+ tmpl := template.Must(template.New("render-entry-api-structs").Parse(apiStructsTmpl))
+
+ specs := createStructSpecs(structApiType, spec, nil)
+ type context struct {
+ Specs []entryStructContext
+ }
+
+ data := context{Specs: specs}
+
+ var builder strings.Builder
+ if err := tmpl.Execute(&builder, data); err != nil {
+ return "", err
+ }
+
+ return builder.String(), nil
+}
+
+const xmlStructsTmpl = `
+{{- range .Specs }}
+{{- $spec := . }}
+type {{ .XmlStructName }} struct{
+ {{- range .Fields }}
+ {{ .Name.CamelCase }} {{ .FinalXmlType }} {{ .Tags }}
+ {{- end }}
+}
+{{- end }}
+`
+
+func RenderEntryXmlStructs(spec *properties.Normalization) (string, error) {
+ tmpl := template.Must(template.New("render-entry-xml-structs").Parse(xmlStructsTmpl))
+
+ specs := createStructSpecs(structXmlType, spec, nil)
+ for _, elt := range spec.SupportedVersionRanges() {
+ specs = append(specs, createStructSpecs(structXmlType, spec, &elt.Minimum)...)
+ }
+
+ type context struct {
+ Specs []entryStructContext
+ }
+
+ data := context{Specs: specs}
+
+ var builder strings.Builder
+ if err := tmpl.Execute(&builder, data); err != nil {
+ return "", err
+ }
+
+ return builder.String(), nil
+}
+
+const structToXmlMarshalersTmpl = `
+{{- range .Specs }}
+ {{- if .IsXmlContainer }}{{ continue }}{{ end }}
+func (o *{{ .XmlStructName }}) MarshalFromObject(s {{ .StructName }}) {
+ {{- range .Fields }}
+ {{- if .IsInternal }}{{ continue }}{{- end }}
+ {{- if eq .FieldType "object" }}
+ if s.{{ .Name.CamelCase }} != nil {
+ var obj {{ .XmlType }}
+ obj.MarshalFromObject(*s.{{ .Name.CamelCase }})
+ o.{{ .Name.CamelCase }} = &obj
+ }
+ {{- else if eq .FieldType "list-member" }}
+ if s.{{ .Name.CamelCase }} != nil {
+ o.{{ .Name.CamelCase }} = util.StrToMem(s.{{ .Name.CamelCase }})
+ }
+ {{- else if eq .FieldType "list-entry" }}
+ if s.{{ .Name.CamelCase }} != nil {
+ var objs {{ .ItemsXmlType }}
+ for _, elt := range s.{{ .Name.CamelCase }} {
+ var obj {{ .XmlType }}
+ obj.MarshalFromObject(elt)
+ objs = append(objs, obj)
+ }
+ o.{{ .Name.CamelCase }} = &{{ .XmlContainerType }}{ Entries: objs }
+ }
+ {{- else if and (eq .FieldType "simple") (eq .Type "bool") }}
+ o.{{ .Name.CamelCase }} = util.YesNo(s.{{ .Name.CamelCase }}, nil)
+ {{- else }}
+ o.{{ .Name.CamelCase }} = s.{{ .Name.CamelCase }}
+ {{- end }}
+ {{- end }}
+}
+
+func (o {{ .XmlStructName }}) UnmarshalToObject() *{{ .StructName }} {
+ {{- range .Fields }}
+ {{- if .IsInternal }}{{ continue }}{{- end }}
+ {{- if eq .FieldType "object" }}
+ var {{ .Name.LowerCamelCase }}Val {{ .FinalType }}
+ if o.{{ .Name.CamelCase }} != nil {
+ {{ .Name.LowerCamelCase }}Val = o.{{ .Name.CamelCase }}.UnmarshalToObject()
+ }
+ {{- else if eq .FieldType "list-member" }}
+ var {{ .Name.LowerCamelCase }}Val {{ .FinalType }}
+ if o.{{ .Name.CamelCase }} != nil {
+ {{ .Name.LowerCamelCase }}Val = util.MemToStr(o.{{ .Name.CamelCase }})
+ }
+ {{- else if eq .FieldType "list-entry" }}
+ var {{ .Name.LowerCamelCase }}Val {{ .FinalType }}
+ if o.{{ .Name.CamelCase }} != nil {
+ for _, elt := range o.{{ .Name.CamelCase }}.Entries {
+ {{ .Name.LowerCamelCase }}Val = append({{ .Name.LowerCamelCase }}Val, *elt.UnmarshalToObject())
+ }
+ }
+ {{- end }}
+ {{- end }}
+
+ result := &{{ .StructName }}{
+ {{- range .Fields }}
+ {{- if .IsInternal }}{{- continue }}{{- end }}
+ {{- if or (eq .FieldType "list-member") (eq .FieldType "list-entry") (eq .FieldType "object") }}
+ {{ .Name.CamelCase }}: {{ .Name.LowerCamelCase }}Val,
+ {{- else if and (eq .FieldType "simple") (eq .Type "bool") }}
+ {{ .Name.CamelCase }}: util.AsBool(o.{{ .Name.CamelCase }}, nil),
+ {{- else }}
+ {{ .Name.CamelCase }}: o.{{ .Name.CamelCase }},
+ {{- end }}
+ {{- end }}
+ }
+ return result
+}
+{{- end }}
+`
+
+func RenderToXmlMarshalers(spec *properties.Normalization) (string, error) {
+ tmpl := template.Must(template.New("render-to-xml-marsrhallers").Parse(structToXmlMarshalersTmpl))
+
+ specs := createStructSpecs(structXmlType, spec, nil)
+ for _, elt := range spec.SupportedVersionRanges() {
+ specs = append(specs, createStructSpecs(structXmlType, spec, &elt.Minimum)...)
+ }
+ type context struct {
+ EntryOrConfig string
+ Specs []entryStructContext
+ }
+
+ entryOrConfig := "Entry"
+ if spec.TerraformProviderConfig.ResourceType == properties.TerraformResourceConfig {
+ entryOrConfig = "Config"
+ }
+
+ data := context{
+ EntryOrConfig: entryOrConfig,
+ Specs: specs,
+ }
+
+ var builder strings.Builder
+ if err := tmpl.Execute(&builder, data); err != nil {
+ return "", err
+ }
+
+ return builder.String(), nil
+}
+
+const xmlContainerNormalizersTmpl = `
+{{- range .Specs }}
+{{- if not .TopLevel }}{{ continue }}{{ end }}
+func (o *{{ .XmlContainerStructName }}) Normalize() ([]*{{ $.EntryOrConfig }}, error) {
+ entries := make([]*{{ $.EntryOrConfig }}, 0, len(o.Answer))
+ for _, elt := range o.Answer {
+ entries = append(entries, elt.UnmarshalToObject())
+ }
+
+ return entries, nil
+}
+{{- end }}
+`
+
+func RenderXmlContainerNormalizers(spec *properties.Normalization) (string, error) {
+ tmpl := template.Must(template.New("render-xml-container-normalizers").Parse(xmlContainerNormalizersTmpl))
+
+ specs := createStructSpecs(structXmlType, spec, nil)
+ for _, elt := range spec.SupportedVersionRanges() {
+ specs = append(specs, createStructSpecs(structXmlType, spec, &elt.Minimum)...)
+ }
+ type context struct {
+ EntryOrConfig string
+ Specs []entryStructContext
+ }
+
+ entryOrConfig := "Entry"
+ if spec.TerraformProviderConfig.ResourceType == properties.TerraformResourceConfig {
+ entryOrConfig = "Config"
+ }
+
+ data := context{
+ EntryOrConfig: entryOrConfig,
+ Specs: specs,
+ }
+
+ var builder strings.Builder
+ if err := tmpl.Execute(&builder, data); err != nil {
+ return "", err
+ }
+
+ return builder.String(), nil
+}
+
+const xmlContainerSpecifiersTmpl = `
+{{- range .Specs }}
+{{- if not .TopLevel }}{{ continue }}{{ end }}
+func {{ .SpecifierFuncName $.EntryOrConfig }}(source *{{ $.EntryOrConfig }}) (any, error) {
+ var obj {{ .XmlStructName }}
+ obj.MarshalFromObject(*source)
+ return obj, nil
+}
+{{- end }}
+`
+
+func RenderXmlContainerSpecifiers(spec *properties.Normalization) (string, error) {
+ tmpl := template.Must(template.New("render-xml-container-specifiers").Parse(xmlContainerSpecifiersTmpl))
+
+ specs := createStructSpecs(structXmlType, spec, nil)
+ for _, elt := range spec.SupportedVersionRanges() {
+ specs = append(specs, createStructSpecs(structXmlType, spec, &elt.Minimum)...)
+ }
+ type context struct {
+ EntryOrConfig string
+ Specs []entryStructContext
+ }
+
+ entryOrConfig := "Entry"
+ if spec.TerraformProviderConfig.ResourceType == properties.TerraformResourceConfig {
+ entryOrConfig = "Config"
+ }
+
+ data := context{
+ EntryOrConfig: entryOrConfig,
+ Specs: specs,
+ }
+
+ var builder strings.Builder
+ if err := tmpl.Execute(&builder, data); err != nil {
+ return "", err
+ }
+
+ return builder.String(), nil
+}
+
+const specMatchersTmpl = `
+func SpecMatches(a, b *{{ .EntryOrConfig }}) bool {
+ if a == nil && b == nil {
+ return true
+ }
+
+ if (a == nil && b != nil) || (a != nil && b == nil) {
+ return false
+ }
+
+ return a.matches(b)
+}
+
+{{- range .Specs }}
+ {{ if .IsXmlContainer }}{{ continue }}{{ end }}
+ {{ $spec := . }}
+func (o *{{ .StructName }}) matches(other *{{ .StructName }}) bool {
+ if o == nil && other == nil {
+ return true
+ }
+
+ if (o == nil && other != nil) || (o != nil && other == nil) {
+ return false
+ }
+
+ {{- range .Fields }}
+ {{- if .IsInternal }}{{ continue }}{{ end }}
+ {{- if and $spec.TopLevel (eq .Name.CamelCase "Name") }}{{ continue }}{{ end }}
+ {{- if eq .Name.CamelCase "Misc" }}{{ continue }}{{ end }}
+ {{- if eq .FieldType "object" }}
+ if !o.{{ .Name.CamelCase }}.matches(other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ {{- else if eq .FieldType "list-entry" }}
+ if len(o.{{ .Name.CamelCase }}) != len(other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ for idx := range o.{{ .Name.CamelCase }} {
+ if !o.{{ .Name.CamelCase }}[idx].matches(&other.{{ .Name.CamelCase }}[idx]) {
+ return false
+ }
+ }
+ {{- else if eq .FieldType "list-member" }}
+ if !util.OrderedListsMatch(o.{{ .Name.CamelCase}}, other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ {{- else if and (eq .Type "string") (eq .Required false)}}
+ if !util.StringsMatch(o.{{ .Name.CamelCase }}, other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ {{- else if and (eq .Type "int64") (eq .Required false)}}
+ if !util.Ints64Match(o.{{ .Name.CamelCase }}, other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ {{- else if and (eq .Type "int64") (eq .Required false)}}
+ if !util.Ints64Match(o.{{ .Name.CamelCase }}, other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ {{- else if and (eq .Type "bool") (eq .Required false)}}
+ if !util.BoolsMatch(o.{{ .Name.CamelCase }}, other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ {{- else if and (eq .Type "float64") (eq .Required false)}}
+ if !util.FloatsMatch(o.{{ .Name.CamelCase }}, other.{{ .Name.CamelCase }}) {
+ return false
+ }
+ {{- else }}
+ if o.{{ .Name.CamelCase }} != other.{{ .Name.CamelCase }} {
+ return false
+ }
+ {{- end }}
+ {{- end }}
+
+ return true
+}
+{{- end }}
+`
+
+func RenderSpecMatchers(spec *properties.Normalization) (string, error) {
+ tmpl := template.Must(template.New("render-spec-matchers").Parse(specMatchersTmpl))
+
+ specs := createStructSpecs(structApiType, spec, nil)
+ type context struct {
+ EntryOrConfig string
+ Specs []entryStructContext
+ }
+
+ entryOrConfig := "Entry"
+ if spec.TerraformProviderConfig.ResourceType == properties.TerraformResourceConfig {
+ entryOrConfig = "Config"
+ }
+
+ data := context{
+ EntryOrConfig: entryOrConfig,
+ Specs: specs,
+ }
+
+ var builder strings.Builder
+ if err := tmpl.Execute(&builder, data); err != nil {
+ return "", err
+ }
+
+ return builder.String(), nil
+}
diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go
index f8b94c3d..a3c9daa7 100644
--- a/pkg/translate/structs_test.go
+++ b/pkg/translate/structs_test.go
@@ -4,6 +4,8 @@ import (
"os"
"testing"
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
"github.com/stretchr/testify/assert"
"github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
@@ -82,39 +84,912 @@ func TestOmitEmpty(t *testing.T) {
assert.Contains(t, omitEmptyLocations, "")
}
-func TestXmlParamType(t *testing.T) {
- // given
- paramTypeRequiredString := properties.SpecParam{
- Type: "string",
- Required: true,
- Profiles: []*properties.SpecParamProfile{
- {
- Type: "string",
- Xpath: []string{"description"},
+var _ = Describe("ParamType", func() {
+ Context("When generating XML types for basic types", func() {
+ structTyp := structXmlType
+ parent := properties.NewNameVariant("")
+ suffix := ""
+ Context("when parameter is not a list", func() {
+ It("should return a normal go type for required params", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "string",
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("string"))
+ })
+ It("should return a pointer to a go type for optional params", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: false,
+ Type: "string",
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("string"))
+ })
+ It("should return string as type for properties with bool type", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: false,
+ Type: "bool",
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("string"))
+ })
+ })
+ Context("when parameter is a list", func() {
+ It("should return a custom pango type for member lists", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "member"}},
+ Items: &properties.SpecParamItems{
+ Type: "string",
+ },
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("util.Member"))
+ })
+ It("should return a custom pango type for optional member lists", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: false,
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "member"}},
+ Items: &properties.SpecParamItems{
+ Type: "string",
+ },
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("util.Member"))
+ })
+ })
+ })
+ Context("When generating XML types for custom types", func() {
+ structTyp := structXmlType
+ Context("when parent is an empty name", func() {
+ parent := properties.NewNameVariant("")
+ Context("and suffix is empty", func() {
+ suffix := ""
+ It("should return a correct XML custom type", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "",
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("testParamXml"))
+ })
+ })
+ Context("and suffix is non-empty", func() {
+ suffix := "_10_2"
+ It("should return a correct XML custom type", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "",
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("testParamXml_10_2"))
+ })
+ })
+ })
+ Context("when parent is non-empty name", func() {
+ parent := properties.NewNameVariant("parent-param")
+ Context("and suffix is empty", func() {
+ suffix := ""
+ It("should return a correct XML custom type prefixed with parent name", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "",
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("parentParamTestParamXml"))
+ })
+ })
+ Context("and suffix is non-empty", func() {
+ suffix := "_10_2"
+ It("should return a correct XML custom type", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "",
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("parentParamTestParamXml_10_2"))
+ })
+ })
+ })
+ })
+ Context("When generating XML types for custom type lists", func() {
+ structTyp := structXmlType
+ Context("when parent is an empty name", func() {
+ parent := properties.NewNameVariant("")
+ Context("and suffix is empty", func() {
+ suffix := ""
+ It("should return a correct XML custom type", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry"}},
+ Items: &properties.SpecParamItems{
+ Type: "object",
+ },
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("testParamXml"))
+ })
+ })
+ Context("and suffix is non-empty", func() {
+ suffix := "_10_2"
+ It("should return a correct XML custom type", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry"}},
+ Items: &properties.SpecParamItems{
+ Type: "object",
+ },
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("testParamXml_10_2"))
+ })
+ })
+ })
+ Context("when parent is non-empty name", func() {
+ parent := properties.NewNameVariant("parent-param")
+ Context("and suffix is empty", func() {
+ suffix := ""
+ It("should return a correct XML custom type prefixed with parent name", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry"}},
+ Items: &properties.SpecParamItems{
+ Type: "object",
+ },
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("parentParamTestParamXml"))
+ })
+ })
+ Context("and suffix is non-empty", func() {
+ suffix := "_10_2"
+ It("should return a correct XML custom type", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("test-param"),
+ Required: true,
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry"}},
+ Items: &properties.SpecParamItems{
+ Type: "object",
+ },
+ }
+ Expect(ParamType(structTyp, parent, param, suffix)).To(Equal("parentParamTestParamXml_10_2"))
+ })
+ })
+ })
+ })
+})
+
+var _ = Describe("createEntryXmlStructSpecsForParameter", func() {
+ Context("when creating struct context for a parameter", func() {
+ It("should return a proper struct context", func() {
+ parent := properties.NewNameVariant("parent-param")
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("child-param"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry", Xpath: []string{"child-param"}}},
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "grandchild-param": {
+ Name: properties.NewNameVariant("grandchild-param"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry", Xpath: []string{"grandchild-param"}}},
+ Spec: &properties.Spec{},
+ },
+ },
+ },
+ }
+
+ result := createEntryXmlStructSpecsForParameter(structXmlType, parent, param, nil)
+ Expect(result).To(HaveLen(2))
+
+ Expect(result[0].StructName()).To(Equal("ParentParamChildParam"))
+ Expect(result[0].XmlStructName()).To(Equal("parentParamChildParamXml"))
+ Expect(result[0].Fields[0]).To(Equal(entryStructFieldContext{
+ Name: properties.NewNameVariant("grandchild-param"),
+ FieldType: "object",
+ Type: "ParentParamChildParamGrandchildParam",
+ XmlType: "parentParamChildParamGrandchildParamXml",
+ Tags: "`xml:\"grandchild-param,omitempty\"`",
+ }))
+ Expect(result[0].Fields[0].FinalType()).To(Equal("*ParentParamChildParamGrandchildParam"))
+ Expect(result[0].Fields[0].FinalXmlType()).To(Equal("*parentParamChildParamGrandchildParamXml"))
+ Expect(result[1].StructName()).To(Equal("ParentParamChildParamGrandchildParam"))
+ Expect(result[1].XmlStructName()).To(Equal("parentParamChildParamGrandchildParamXml"))
+ })
+ })
+ Context("when creating struct context for a simple type list parameter", func() {
+ It("should return a proper struct context", func() {
+ parent := properties.NewNameVariant("")
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("parent-param"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry", Xpath: []string{"child-param"}}},
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "child-param": {
+ Name: properties.NewNameVariant("child-param"),
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "member", Xpath: []string{"child-param"}}},
+ Items: &properties.SpecParamItems{
+ Type: "string",
+ },
+ },
+ },
+ },
+ }
+
+ result := createEntryXmlStructSpecsForParameter(structXmlType, parent, param, nil)
+ Expect(result).To(HaveLen(1))
+
+ Expect(result[0].StructName()).To(Equal("ParentParam"))
+ Expect(result[0].XmlStructName()).To(Equal("parentParamXml"))
+ Expect(result[0].Fields[0]).To(Equal(entryStructFieldContext{
+ Name: properties.NewNameVariant("child-param"),
+ FieldType: "list-member",
+ Type: "string",
+ ItemsType: "[]string",
+ XmlType: "util.Member",
+ ItemsXmlType: "util.MemberType",
+ Tags: "`xml:\"child-param,omitempty\"`",
+ }))
+ })
+ })
+ Context("when creating struct context for a complex type list parameter", func() {
+ It("should return a proper struct context", func() {
+ parent := properties.NewNameVariant("")
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("parent-param"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry", Xpath: []string{"child-param"}}},
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "child-param": {
+ Name: properties.NewNameVariant("child-param"),
+ SpecOrder: 0,
+ Type: "list",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry", Xpath: []string{"child-param"}}},
+ Items: &properties.SpecParamItems{
+ Type: "entry",
+ },
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "grandchild-param": {
+ Name: properties.NewNameVariant("grandchild-param"),
+ Type: "int64",
+ Profiles: []*properties.SpecParamProfile{{Xpath: []string{"grandchild-param"}}},
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ result := createEntryXmlStructSpecsForParameter(structXmlType, parent, param, nil)
+ Expect(result).To(HaveLen(3))
+
+ Expect(result[0].StructName()).To(Equal("ParentParam"))
+ Expect(result[0].XmlStructName()).To(Equal("parentParamXml"))
+ Expect(result[0].Fields[0]).To(Equal(entryStructFieldContext{
+ Name: properties.NewNameVariant("child-param"),
+ FieldType: "list-entry",
+ Type: "ParentParamChildParam",
+ ItemsType: "[]ParentParamChildParam",
+ XmlType: "parentParamChildParamXml",
+ XmlContainerType: "parentParamChildParamContainerXml",
+ ItemsXmlType: "[]parentParamChildParamXml",
+ Tags: "`xml:\"child-param,omitempty\"`",
+ }))
+ Expect(result[0].Fields[0].FinalXmlType()).To(Equal("*parentParamChildParamContainerXml"))
+
+ Expect(result[1].IsXmlContainer).To(BeTrue())
+ Expect(result[1].XmlStructName()).To(Equal("parentParamChildParamContainerXml"))
+ Expect(result[1].Fields).To(HaveExactElements([]entryStructFieldContext{
+ {
+ Name: properties.NewNameVariant("entries"),
+ FieldType: "list-entry",
+ Type: "ParentParamChildParam",
+ ItemsType: "[]ParentParamChildParam",
+ XmlType: "parentParamChildParamXml",
+ ItemsXmlType: "[]parentParamChildParamXml",
+ Tags: "`xml:\"entry\"`",
+ },
+ }))
+
+ Expect(result[2].StructName()).To(Equal("ParentParamChildParam"))
+ Expect(result[2].XmlStructName()).To(Equal("parentParamChildParamXml"))
+ Expect(result[2].Fields).To(HaveExactElements([]entryStructFieldContext{
+ {
+ Name: xmlNameVariant,
+ IsInternal: true,
+ Required: false,
+ FieldType: "internal",
+ Type: "",
+ ItemsType: "",
+ XmlType: "xml.Name",
+ ItemsXmlType: "",
+ Tags: "`xml:\"entry\"`",
+ },
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ ItemsType: "",
+ XmlType: "string",
+ ItemsXmlType: "",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("grandchild-param"),
+ FieldType: "simple",
+ Type: "int64",
+ ItemsType: "",
+ XmlType: "int64",
+ ItemsXmlType: "",
+ Tags: "`xml:\"grandchild-param,omitempty\"`",
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+ })
+ })
+ Context("when creating struct context for parameter with versioned children", func() {
+ parent := properties.NewNameVariant("")
+ It("should return all specs when nil version is passed", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("parent-param"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry", Xpath: []string{"child-param"}}},
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "child-param1": {
+ Name: properties.NewNameVariant("child-param1"),
+ SpecOrder: 0,
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"child-param1"},
+ },
+ },
+ Spec: &properties.Spec{},
+ },
+ "child-param2": {
+ Name: properties.NewNameVariant("child-param2"),
+ SpecOrder: 1,
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"child-param2"},
+ },
+ },
+ Spec: &properties.Spec{},
+ },
+ },
+ },
+ }
+
+ result := createEntryXmlStructSpecsForParameter(structXmlType, parent, param, nil)
+ Expect(result).To(HaveLen(3))
+
+ Expect(result[0].StructName()).To(Equal("ParentParam"))
+ Expect(result[0].XmlStructName()).To(Equal("parentParamXml"))
+ Expect(result[0].Fields).To(HaveExactElements([]entryStructFieldContext{
+ {
+ Name: properties.NewNameVariant("child-param1"),
+ FieldType: "object",
+ Type: "ParentParamChildParam1",
+ XmlType: "parentParamChildParam1Xml",
+ Tags: "`xml:\"child-param1,omitempty\"`",
+ },
+ {
+ Name: properties.NewNameVariant("child-param2"),
+ FieldType: "object",
+ Type: "ParentParamChildParam2",
+ XmlType: "parentParamChildParam2Xml",
+ Tags: "`xml:\"child-param2,omitempty\"`",
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+
+ Expect(result[0].Fields[0].FinalType()).To(Equal("*ParentParamChildParam1"))
+ Expect(result[0].Fields[0].FinalXmlType()).To(Equal("*parentParamChildParam1Xml"))
+
+ Expect(result[0].Fields[1].FinalType()).To(Equal("*ParentParamChildParam2"))
+ Expect(result[0].Fields[1].FinalXmlType()).To(Equal("*parentParamChildParam2Xml"))
+
+ Expect(result[1].StructName()).To(Equal("ParentParamChildParam1"))
+ Expect(result[1].XmlStructName()).To(Equal("parentParamChildParam1Xml"))
+ Expect(result[2].StructName()).To(Equal("ParentParamChildParam2"))
+ Expect(result[2].XmlStructName()).To(Equal("parentParamChildParam2Xml"))
+ })
+ It("should only return relevant specs when version is non-nill", func() {
+ param := &properties.SpecParam{
+ Name: properties.NewNameVariant("parent-param"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{{Type: "entry", Xpath: []string{"child-param"}}},
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "child-param1": {
+ Name: properties.NewNameVariant("child-param1"),
+ SpecOrder: 0,
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"child-param1"},
+ },
+ },
+ Spec: &properties.Spec{},
+ },
+ "child-param2": {
+ Name: properties.NewNameVariant("child-param2"),
+ SpecOrder: 1,
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"child-param2"},
+ MinVersion: version.MustNewVersionFromString("11.0.0"),
+ MaxVersion: version.MustNewVersionFromString("11.0.5"),
+ },
+ },
+ Spec: &properties.Spec{},
+ },
+ },
+ },
+ }
+ paramVersion := version.MustNewVersionFromString("10.0.0")
+ result := createEntryXmlStructSpecsForParameter(structXmlType, parent, param, paramVersion)
+ Expect(result).To(HaveLen(2))
+
+ Expect(result[0].StructName()).To(Equal("ParentParam"))
+ Expect(result[0].XmlStructName()).To(Equal("parentParamXml_10_0_0"))
+ Expect(result[0].Fields).To(HaveExactElements([]entryStructFieldContext{
+ {
+ Name: properties.NewNameVariant("child-param1"),
+ FieldType: "object",
+ Type: "ParentParamChildParam1",
+ XmlType: "parentParamChildParam1Xml_10_0_0",
+ Tags: "`xml:\"child-param1,omitempty\"`",
+ version: paramVersion,
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+
+ Expect(result[1].StructName()).To(Equal("ParentParamChildParam1"))
+ Expect(result[1].XmlStructName()).To(Equal("parentParamChildParam1Xml_10_0_0"))
+ })
+ })
+})
+
+var _ = Describe("createStructSpecs", func() {
+ Context("when generating xml struct specs for a spec without parameters", func() {
+ It("should return a list of struct specs with a single element", func() {
+ spec := &properties.Normalization{
+ TerraformProviderConfig: properties.TerraformProviderConfig{
+ ResourceType: properties.TerraformResourceEntry,
+ },
+ Name: "test-spec",
+ Spec: &properties.Spec{},
+ }
+
+ result := createStructSpecs(structXmlType, spec, nil)
+ Expect(result).To(HaveLen(1))
+
+ Expect(result[0].StructName()).To(Equal("Entry"))
+ Expect(result[0].XmlStructName()).To(Equal("entryXml"))
+ Expect(result[0].Fields[0].Name.CamelCase).To(Equal("XMLName"))
+ Expect(result[0].Fields).To(HaveExactElements([]entryStructFieldContext{
+ {
+ Name: xmlNameVariant,
+ FieldType: "internal",
+ IsInternal: true,
+ XmlType: "xml.Name",
+ Tags: "`xml:\"entry\"`",
+ },
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+ })
+ })
+ Context("when generating struct specs for a spec with entry lists", func() {
+ spec := &properties.Normalization{
+ TerraformProviderConfig: properties.TerraformProviderConfig{
+ ResourceType: properties.TerraformResourceEntry,
},
- },
- }
- paramTypeListString := properties.SpecParam{
- Type: "list",
- Items: &properties.SpecParamItems{
- Type: "string",
- },
- Profiles: []*properties.SpecParamProfile{
- {
- Type: "member",
- Xpath: []string{"tag"},
+ Name: "test-spec",
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "param-one": {
+ Name: properties.NewNameVariant("param-one"),
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"param-one"},
+ },
+ },
+ Type: "list",
+ Items: &properties.SpecParamItems{
+ Type: "entry",
+ },
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "param-two": {
+ Name: properties.NewNameVariant("param-two"),
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Xpath: []string{"param-two"},
+ },
+ },
+ Type: "int64",
+ },
+ },
+ },
+ },
+ },
},
- },
- }
+ }
+ Context("and the struct type is structApiType", func() {
+ It("should create a parent spec and a single child spec", func() {
+ result := createStructSpecs(structApiType, spec, nil)
- // when
- calculatedTypeRequiredString := XmlParamType("", ¶mTypeRequiredString)
- calculatedTypeListString := XmlParamType("", ¶mTypeListString)
+ Expect(result).To(HaveLen(2))
+ Expect(result[0].name).To(Equal(properties.NewNameVariant("entry")))
+ Expect(result[0].Fields).To(Equal([]entryStructFieldContext{
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("param-one"),
+ FieldType: "list-entry",
+ Type: "ParamOne",
+ ItemsType: "[]ParamOne",
+ XmlType: "paramOneXml",
+ ItemsXmlType: "[]paramOneXml",
+ Tags: "`xml:\"param-one,omitempty\"`",
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+ Expect(result[1].name).To(Equal(properties.NewNameVariant("param-one")))
+ Expect(result[1].Fields).To(Equal([]entryStructFieldContext{
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("param-two"),
+ FieldType: "simple",
+ Type: "int64",
+ ItemsType: "",
+ XmlType: "int64",
+ ItemsXmlType: "",
+ Tags: "`xml:\"param-two,omitempty\"`",
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+ })
+ })
+ Context("and the struct type is structXmlType", func() {
+ It("should create a parent spec and two child specs", func() {
+ result := createStructSpecs(structXmlType, spec, nil)
- // then
- assert.Equal(t, "string", calculatedTypeRequiredString)
- assert.Equal(t, "*util.MemberType", calculatedTypeListString)
-}
+ Expect(result).To(HaveLen(3))
+ Expect(result[0].name).To(Equal(properties.NewNameVariant("entry")))
+ Expect(result[0].Fields).To(Equal([]entryStructFieldContext{
+ {
+ Name: xmlNameVariant,
+ FieldType: "internal",
+ IsInternal: true,
+ XmlType: "xml.Name",
+ Tags: "`xml:\"entry\"`",
+ },
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("param-one"),
+ FieldType: "list-entry",
+ Type: "ParamOne",
+ ItemsType: "[]ParamOne",
+ XmlType: "paramOneXml",
+ XmlContainerType: "paramOneContainerXml",
+ ItemsXmlType: "[]paramOneXml",
+ Tags: "`xml:\"param-one,omitempty\"`",
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+
+ Expect(result[1].name).To(Equal(properties.NewNameVariant("param-one-container")))
+ Expect(result[1].Fields).To(Equal([]entryStructFieldContext{
+ {
+ Name: properties.NewNameVariant("entries"),
+ FieldType: "list-entry",
+ Type: "ParamOne",
+ ItemsType: "[]ParamOne",
+ XmlType: "paramOneXml",
+ ItemsXmlType: "[]paramOneXml",
+ Tags: "`xml:\"entry\"`",
+ },
+ }))
+
+ Expect(result[2].name).To(Equal(properties.NewNameVariant("param-one")))
+ Expect(result[2].Fields).To(Equal([]entryStructFieldContext{
+ {
+ Name: xmlNameVariant,
+ FieldType: "internal",
+ IsInternal: true,
+ XmlType: "xml.Name",
+ Tags: "`xml:\"entry\"`",
+ },
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("param-two"),
+ FieldType: "simple",
+ Type: "int64",
+ ItemsType: "",
+ XmlType: "int64",
+ ItemsXmlType: "",
+ Tags: "`xml:\"param-two,omitempty\"`",
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+ })
+ })
+ })
+ Context("when generating xml struct specs for a spec with one object parameter", func() {
+ It("should return a list of two specs", func() {
+ version11_0_0 := version.MustNewVersionFromString("11.0.0")
+ version11_0_3 := version.MustNewVersionFromString("11.0.3")
+ spec := &properties.Normalization{
+ TerraformProviderConfig: properties.TerraformProviderConfig{
+ ResourceType: properties.TerraformResourceEntry,
+ },
+ Name: "test-spec",
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "param-one": {
+ Name: properties.NewNameVariant("param-one"),
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"param-one"},
+ MinVersion: version11_0_3,
+ MaxVersion: version.MustNewVersionFromString("11.0.5"),
+ },
+ },
+ Type: "bool",
+ },
+ },
+ OneOf: map[string]*properties.SpecParam{
+ "param-two": {
+ Name: properties.NewNameVariant("param-two"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"param-two"},
+ },
+ },
+ Items: &properties.SpecParamItems{
+ Type: "object",
+ },
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "param-three": {
+ Name: properties.NewNameVariant("param-three"),
+ Type: "",
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Type: "entry",
+ Xpath: []string{"param-three"},
+ MinVersion: version11_0_0,
+ MaxVersion: version.MustNewVersionFromString("11.0.5"),
+ },
+ },
+ Items: &properties.SpecParamItems{
+ Type: "object",
+ },
+ Spec: &properties.Spec{
+ Params: map[string]*properties.SpecParam{
+ "param-four": {
+ Name: properties.NewNameVariant("param-four"),
+ Profiles: []*properties.SpecParamProfile{
+ {
+ Xpath: []string{"param-four"},
+ },
+ },
+ Type: "int64",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ result := createStructSpecs(structXmlType, spec, nil)
+ Expect(result).To(HaveLen(3))
+
+ Expect(result[0].XmlStructName()).To(Equal("entryXml"))
+ Expect(result[1].XmlStructName()).To(Equal("paramTwoXml"))
+ Expect(result[2].XmlStructName()).To(Equal("paramTwoParamThreeXml"))
+
+ result = createStructSpecs(structXmlType, spec, version11_0_3)
+ Expect(result).To(HaveLen(3))
+ Expect(result[0].XmlStructName()).To(Equal("entryXml_11_0_3"))
+ Expect(result[1].XmlStructName()).To(Equal("paramTwoXml_11_0_3"))
+ Expect(result[2].XmlStructName()).To(Equal("paramTwoParamThreeXml_11_0_3"))
+
+ Expect(result[0].Fields).To(HaveExactElements([]entryStructFieldContext{
+ {
+ Name: xmlNameVariant,
+ FieldType: "internal",
+ IsInternal: true,
+ XmlType: "xml.Name",
+ Tags: "`xml:\"entry\"`",
+ },
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("param-one"),
+ FieldType: "simple",
+ Type: "bool",
+ XmlType: "string",
+ Tags: "`xml:\"param-one,omitempty\"`",
+ version: version11_0_3,
+ },
+ {
+ Name: properties.NewNameVariant("param-two"),
+ FieldType: "object",
+ Type: "ParamTwo",
+ XmlType: "paramTwoXml_11_0_3",
+ Tags: "`xml:\"param-two,omitempty\"`",
+ version: version11_0_3,
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+
+ result = createStructSpecs(structXmlType, spec, version11_0_0)
+ Expect(result).To(HaveLen(3))
+ Expect(result[0].XmlStructName()).To(Equal("entryXml_11_0_0"))
+ Expect(result[1].XmlStructName()).To(Equal("paramTwoXml_11_0_0"))
+ Expect(result[2].XmlStructName()).To(Equal("paramTwoParamThreeXml_11_0_0"))
+
+ Expect(result[0].Fields).To(HaveExactElements([]entryStructFieldContext{
+ {
+ Name: xmlNameVariant,
+ FieldType: "internal",
+ IsInternal: true,
+ XmlType: "xml.Name",
+ Tags: "`xml:\"entry\"`",
+ },
+ {
+ Name: properties.NewNameVariant("name"),
+ Required: true,
+ FieldType: "simple",
+ Type: "string",
+ XmlType: "string",
+ Tags: "`xml:\"name,attr\"`",
+ },
+ {
+ Name: properties.NewNameVariant("param-two"),
+ FieldType: "object",
+ Type: "ParamTwo",
+ XmlType: "paramTwoXml_11_0_0",
+ Tags: "`xml:\"param-two,omitempty\"`",
+ version: version11_0_0,
+ },
+ {
+ Name: properties.NewNameVariant("misc"),
+ FieldType: "internal",
+ Type: "[]generic.Xml",
+ XmlType: "[]generic.Xml",
+ Tags: "`xml:\",any\"`",
+ },
+ }))
+ })
+ })
+})
func TestXmlTag(t *testing.T) {
// given
@@ -163,39 +1038,6 @@ func TestXmlTag(t *testing.T) {
assert.Equal(t, "`xml:\"uuid,attr,omitempty\"`", calculatedXmlTagUuid)
}
-func TestNestedSpecs(t *testing.T) {
- // given
- spec := properties.Spec{
- Params: map[string]*properties.SpecParam{
- "a": {
- Name: properties.NewNameVariant("a"),
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "b": {
- Name: properties.NewNameVariant("b"),
- Spec: &properties.Spec{
- Params: map[string]*properties.SpecParam{
- "c": {
- Name: properties.NewNameVariant("c"),
- },
- },
- },
- },
- },
- },
- },
- },
- }
-
- // when
- nestedSpecs, _ := NestedSpecs(&spec)
-
- // then
- assert.NotNil(t, nestedSpecs)
- assert.Contains(t, nestedSpecs, "A")
- assert.Contains(t, nestedSpecs, "AB")
-}
-
func TestCreateGoSuffixFromVersion(t *testing.T) {
// given
diff --git a/pkg/translate/terraform_provider/funcs.go b/pkg/translate/terraform_provider/funcs.go
index f942de7b..8d689187 100644
--- a/pkg/translate/terraform_provider/funcs.go
+++ b/pkg/translate/terraform_provider/funcs.go
@@ -3,6 +3,7 @@ package terraform_provider
import (
"fmt"
"log"
+ "runtime/debug"
"sort"
"strings"
"text/template"
@@ -13,6 +14,7 @@ import (
"github.com/paloaltonetworks/pan-os-codegen/pkg/imports"
"github.com/paloaltonetworks/pan-os-codegen/pkg/naming"
"github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
+ "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/object"
)
type Entry struct {
@@ -55,9 +57,14 @@ type spec struct {
func renderSpecsForParams(params []*properties.SpecParam, parentNames []string) []parameterSpec {
var specs []parameterSpec
for _, elt := range params {
+ if elt.IsTerraformOnly() {
+ continue
+ }
+
if elt.IsPrivateParameter() {
continue
}
+
var encryptionSpec *parameterEncryptionSpec
if elt.Hashing != nil {
path := strings.Join(append(parentNames, elt.Name.Underscore), " | ")
@@ -164,7 +171,7 @@ func generateFromTerraformToPangoParameter(resourceTyp properties.ResourceType,
case properties.ResourceEntryPlural, properties.ResourceUuid, properties.ResourceUuidPlural:
terraformPrefix = fmt.Sprintf("%s%s", terraformPrefix, pascalCase(prop.TerraformProviderConfig.PluralName))
var hasEntryName bool
- if prop.Entry != nil && resourceTyp != properties.ResourceEntryPlural {
+ if prop.Entry != nil && (resourceTyp != properties.ResourceEntryPlural || prop.TerraformProviderConfig.PluralType != object.TerraformPluralMapType) {
hasEntryName = true
}
specs = append(specs, spec{
@@ -638,6 +645,74 @@ func RenderCopyFromPangoFunctions(resourceTyp properties.ResourceType, pkgName s
return processTemplate(copyFromPangoTmpl, "copy-from-pango", data, funcMap)
}
+const xpathComponentsGetterTmpl = `
+func (o *{{ .StructName }}Model) resourceXpathParentComponents() ([]string, error) {
+ var components []string
+{{- range .Components }}
+ {{- if eq .Type "value" }}
+ components = append(components, (o.{{ .Name.CamelCase }}.ValueString()))
+ {{- else if eq .Type "entry" }}
+ components = append(components, pangoutil.AsEntryXpath(o.{{ .Name.CamelCase }}.ValueString()))
+ {{- end }}
+{{- end }}
+ return components, nil
+}
+`
+
+func RenderXpathComponentsGetter(structName string, property *properties.Normalization) (string, error) {
+ defer func() {
+ if e := recover(); e != nil {
+ log.Printf("** PANIC: %v", e)
+ debug.PrintStack()
+ panic(e)
+ }
+ }()
+
+ type componentSpec struct {
+ Type string
+ Name *properties.NameVariant
+ Variants []*properties.NameVariant
+ }
+
+ var components []componentSpec
+ for _, elt := range property.PanosXpath.Variables {
+ if elt.Name == "name" {
+ continue
+ }
+
+ xpathProperty, err := property.ParameterForPanosXpathVariable(elt)
+ if err != nil {
+ return "", err
+ }
+
+ switch elt.Spec.Type {
+ case object.PanosXpathVariableValue:
+ components = append(components, componentSpec{
+ Type: "value",
+ Name: xpathProperty.Name,
+ })
+ case object.PanosXpathVariableEntry:
+ components = append(components, componentSpec{
+ Type: "entry",
+ Name: xpathProperty.Name,
+ })
+ case object.PanosXpathVariableStatic:
+ default:
+ panic(fmt.Sprintf("invalid panos xpath variable type: '%s'", elt.Spec.Type))
+ }
+ }
+
+ data := struct {
+ StructName string
+ Components []componentSpec
+ }{
+ StructName: structName,
+ Components: components,
+ }
+
+ return processTemplate(xpathComponentsGetterTmpl, "xpath-components", data, commonFuncMap)
+}
+
const renderLocationTmpl = `
{{- range .Locations }}
type {{ .StructName }} struct {
@@ -1523,14 +1598,42 @@ func createSchemaSpecForEntryListModel(resourceTyp properties.ResourceType, sche
listNameStr := spec.TerraformProviderConfig.PluralName
listName := properties.NewNameVariant(listNameStr)
+ var listAttributeSchemaType string
+ switch spec.TerraformProviderConfig.PluralType {
+ case object.TerraformPluralListType:
+ listAttributeSchemaType = "ListNestedAttribute"
+ case object.TerraformPluralMapType:
+ listAttributeSchemaType = "MapNestedAttribute"
+ case object.TerraformPluralSetType:
+ listAttributeSchemaType = "SetNestedAttribute"
+ }
+
attributes = append(attributes, attributeCtx{
Package: packageName,
Name: listName,
Description: spec.TerraformProviderConfig.PluralDescription,
Required: true,
- SchemaType: "MapNestedAttribute",
+ SchemaType: listAttributeSchemaType,
})
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "name" {
+ continue
+ }
+
+ param, err := spec.ParameterForPanosXpathVariable(elt)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ attributes = append(attributes, attributeCtx{
+ Package: packageName,
+ Name: param.Name,
+ Required: true,
+ SchemaType: "StringAttribute",
+ })
+ }
+
var isResource bool
if schemaTyp == properties.SchemaResource {
isResource = true
@@ -1624,9 +1727,9 @@ func createSchemaSpecForNormalization(resourceTyp properties.ResourceType, schem
})
}
- // We don't add name for resources of type ResourceEntryPlural, as those resources
+ // We don't add name for resources that have plurar type set to map, as those resources
// handle names as map keys in the top-level model.
- if spec.HasEntryName() && resourceTyp != properties.ResourceEntryPlural {
+ if spec.HasEntryName() && (resourceTyp != properties.ResourceEntryPlural || spec.TerraformProviderConfig.PluralType != object.TerraformPluralMapType) {
name := properties.NewNameVariant("name")
var description string
@@ -1648,6 +1751,10 @@ func createSchemaSpecForNormalization(resourceTyp properties.ResourceType, schem
continue
}
+ if resourceTyp == properties.ResourceEntryPlural && elt.TerraformProviderConfig != nil && elt.TerraformProviderConfig.XpathVariable != nil {
+ continue
+ }
+
var functions []validatorFunctionCtx
if len(elt.EnumValues) > 0 && schemaTyp == properties.SchemaResource {
var values []string
@@ -1685,6 +1792,10 @@ func createSchemaSpecForNormalization(resourceTyp properties.ResourceType, schem
continue
}
+ if resourceTyp == properties.ResourceEntryPlural && elt.TerraformProviderConfig != nil && elt.TerraformProviderConfig.XpathVariable != nil {
+ continue
+ }
+
var validators *validatorCtx
if schemaTyp == properties.SchemaResource {
validatorFn, found := validatorFns[elt.VariantGroupId]
@@ -2384,13 +2495,41 @@ func createStructSpecForEntryListModel(resourceTyp properties.ResourceType, sche
panic("unreachable")
}
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "name" {
+ continue
+ }
+
+ param, err := spec.ParameterForPanosXpathVariable(elt)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ xmlTags := []string{fmt.Sprintf("`tfsdk:\"%s\"`", param.Name.Underscore)}
+ fields = append(fields, datasourceStructFieldSpec{
+ Name: param.Name,
+ Type: "types.String",
+ Tags: xmlTags,
+ })
+ }
+
listNameStr := spec.TerraformProviderConfig.PluralName
listName := properties.NewNameVariant(listNameStr)
+ var listEltType string
+ switch spec.TerraformProviderConfig.PluralType {
+ case object.TerraformPluralMapType:
+ listEltType = "types.Map"
+ case object.TerraformPluralListType:
+ listEltType = "types.List"
+ case object.TerraformPluralSetType:
+ listEltType = "types.Set"
+ }
+
tag := fmt.Sprintf("`tfsdk:\"%s\"`", listName.Underscore)
fields = append(fields, datasourceStructFieldSpec{
Name: listName,
- Type: "types.Map",
+ Type: listEltType,
Tags: []string{tag},
})
@@ -2475,7 +2614,7 @@ func createStructSpecForNormalization(resourceTyp properties.ResourceType, struc
// We don't add name field for entry-style list resources, as they
// represent lists as maps with name being a key.
- if spec.HasEntryName() && resourceTyp != properties.ResourceEntryPlural {
+ if spec.HasEntryName() && (resourceTyp != properties.ResourceEntryPlural || spec.TerraformProviderConfig.PluralType != object.TerraformPluralMapType) {
fields = append(fields, datasourceStructFieldSpec{
Name: properties.NewNameVariant("name"),
Type: "types.String",
@@ -2488,6 +2627,10 @@ func createStructSpecForNormalization(resourceTyp properties.ResourceType, struc
continue
}
+ if resourceTyp == properties.ResourceEntryPlural && elt.TerraformProviderConfig != nil && elt.TerraformProviderConfig.XpathVariable != nil {
+ continue
+ }
+
fields = append(fields, structFieldSpec(elt, structName, hackStructAsTypeObjects))
if elt.Type == "" || (elt.Type == "list" && elt.Items.Type == "entry") {
structs = append(structs, dataSourceStructContextForParam(structName, elt, hackStructAsTypeObjects)...)
@@ -2499,6 +2642,10 @@ func createStructSpecForNormalization(resourceTyp properties.ResourceType, struc
continue
}
+ if resourceTyp == properties.ResourceEntryPlural && elt.TerraformProviderConfig != nil && elt.TerraformProviderConfig.XpathVariable != nil {
+ continue
+ }
+
fields = append(fields, structFieldSpec(elt, structName, hackStructAsTypeObjects))
if elt.Type == "" || (elt.Type == "list" && elt.Items.Type == "entry") {
structs = append(structs, dataSourceStructContextForParam(structName, elt, hackStructAsTypeObjects)...)
@@ -2679,15 +2826,11 @@ func ResourceCreateFunction(resourceTyp properties.ResourceType, names *NameProv
listAttributeVariant := properties.NewNameVariant(listAttribute)
- var resourceIsMap bool
- if resourceTyp == properties.ResourceEntryPlural {
- resourceIsMap = true
- }
data := map[string]interface{}{
+ "PluralType": paramSpec.TerraformProviderConfig.PluralType,
"HasEncryptedResources": paramSpec.HasEncryptedResources(),
"HasImports": len(paramSpec.Imports) > 0,
"Exhaustive": exhaustive,
- "ResourceIsMap": resourceIsMap,
"ListAttribute": listAttributeVariant,
"EntryOrConfig": paramSpec.EntryOrConfig(),
"HasEntryName": paramSpec.HasEntryName(),
@@ -2732,27 +2875,25 @@ func DataSourceReadFunction(resourceTyp properties.ResourceType, names *NameProv
listAttributeVariant := properties.NewNameVariant(listAttribute)
- var resourceIsMap bool
- if resourceTyp == properties.ResourceEntryPlural {
- resourceIsMap = true
- }
data := map[string]interface{}{
- "ResourceOrDS": "DataSource",
- "ResourceIsMap": resourceIsMap,
- "HasEncryptedResources": paramSpec.HasEncryptedResources(),
- "ListAttribute": listAttributeVariant,
- "Exhaustive": exhaustive,
- "EntryOrConfig": paramSpec.EntryOrConfig(),
- "HasEntryName": paramSpec.HasEntryName(),
- "structName": names.StructName,
- "resourceStructName": names.ResourceStructName,
- "dataSourceStructName": names.DataSourceStructName,
- "serviceName": naming.CamelCase("", serviceName, "", false),
- "resourceSDKName": resourceSDKName,
- "locations": paramSpec.OrderedLocations(),
+ "PluralType": paramSpec.TerraformProviderConfig.PluralType,
+ "ResourceXpathVariablesWithChecks": paramSpec.ResourceXpathVariablesWithChecks(false),
+ "ResourceOrDS": "DataSource",
+ "HasEncryptedResources": paramSpec.HasEncryptedResources(),
+ "ListAttribute": listAttributeVariant,
+ "Exhaustive": exhaustive,
+ "EntryOrConfig": paramSpec.EntryOrConfig(),
+ "HasEntryName": paramSpec.HasEntryName(),
+ "structName": names.StructName,
+ "resourceStructName": names.ResourceStructName,
+ "dataSourceStructName": names.DataSourceStructName,
+ "serviceName": naming.CamelCase("", serviceName, "", false),
+ "resourceSDKName": resourceSDKName,
+ "locations": paramSpec.OrderedLocations(),
}
funcMap := template.FuncMap{
+ "AttributesFromXpathComponents": func(target string) (string, error) { return paramSpec.AttributesFromXpathComponents(target) },
"RenderLocationsPangoToState": func(source string, dest string) (string, error) {
return RenderLocationsPangoToState(names, paramSpec, source, dest)
},
@@ -2761,7 +2902,7 @@ func DataSourceReadFunction(resourceTyp properties.ResourceType, names *NameProv
},
}
- return processTemplate(tmpl, "resource-read-function", data, funcMap)
+ return processTemplate(tmpl, "datasource-read-function", data, funcMap)
}
func ResourceReadFunction(resourceTyp properties.ResourceType, names *NameProvider, serviceName string, paramSpec *properties.Normalization, resourceSDKName string) (string, error) {
@@ -2795,27 +2936,25 @@ func ResourceReadFunction(resourceTyp properties.ResourceType, names *NameProvid
listAttributeVariant := properties.NewNameVariant(listAttribute)
- var resourceIsMap bool
- if resourceTyp == properties.ResourceEntryPlural {
- resourceIsMap = true
- }
data := map[string]interface{}{
- "ResourceOrDS": "Resource",
- "ResourceIsMap": resourceIsMap,
- "HasEncryptedResources": paramSpec.HasEncryptedResources(),
- "ListAttribute": listAttributeVariant,
- "Exhaustive": exhaustive,
- "EntryOrConfig": paramSpec.EntryOrConfig(),
- "HasEntryName": paramSpec.HasEntryName(),
- "structName": names.StructName,
- "datasourceStructName": names.DataSourceStructName,
- "resourceStructName": names.ResourceStructName,
- "serviceName": naming.CamelCase("", serviceName, "", false),
- "resourceSDKName": resourceSDKName,
- "locations": paramSpec.OrderedLocations(),
+ "PluralType": paramSpec.TerraformProviderConfig.PluralType,
+ "ResourceXpathVariablesWithChecks": paramSpec.ResourceXpathVariablesWithChecks(false),
+ "ResourceOrDS": "Resource",
+ "HasEncryptedResources": paramSpec.HasEncryptedResources(),
+ "ListAttribute": listAttributeVariant,
+ "Exhaustive": exhaustive,
+ "EntryOrConfig": paramSpec.EntryOrConfig(),
+ "HasEntryName": paramSpec.HasEntryName(),
+ "structName": names.StructName,
+ "datasourceStructName": names.DataSourceStructName,
+ "resourceStructName": names.ResourceStructName,
+ "serviceName": naming.CamelCase("", serviceName, "", false),
+ "resourceSDKName": resourceSDKName,
+ "locations": paramSpec.OrderedLocations(),
}
funcMap := template.FuncMap{
+ "AttributesFromXpathComponents": func(target string) (string, error) { return paramSpec.AttributesFromXpathComponents(target) },
"RenderLocationsPangoToState": func(source string, dest string) (string, error) {
return RenderLocationsPangoToState(names, paramSpec, source, dest)
},
@@ -2858,14 +2997,9 @@ func ResourceUpdateFunction(resourceTyp properties.ResourceType, names *NameProv
listAttributeVariant := properties.NewNameVariant(listAttribute)
- var resourceIsMap bool
- if resourceTyp == properties.ResourceEntryPlural {
- resourceIsMap = true
- }
-
data := map[string]interface{}{
+ "PluralType": paramSpec.TerraformProviderConfig.PluralType,
"HasEncryptedResources": paramSpec.HasEncryptedResources(),
- "ResourceIsMap": resourceIsMap,
"ListAttribute": listAttributeVariant,
"Exhaustive": exhaustive,
"EntryOrConfig": paramSpec.EntryOrConfig(),
@@ -2897,7 +3031,7 @@ func ResourceDeleteFunction(resourceTyp properties.ResourceType, names *NameProv
var tmpl string
var listAttribute string
- var exhaustive bool
+ var exhaustive string
switch resourceTyp {
case properties.ResourceEntry, properties.ResourceConfig:
tmpl = resourceDeleteFunction
@@ -2907,10 +3041,11 @@ func ResourceDeleteFunction(resourceTyp properties.ResourceType, names *NameProv
case properties.ResourceUuid:
tmpl = resourceDeleteManyFunction
listAttribute = pascalCase(paramSpec.TerraformProviderConfig.PluralName)
- exhaustive = true
+ exhaustive = "exhaustive"
case properties.ResourceUuidPlural:
tmpl = resourceDeleteManyFunction
listAttribute = pascalCase(paramSpec.TerraformProviderConfig.PluralName)
+ exhaustive = "non-exhaustive"
case properties.ResourceCustom:
var err error
tmpl, err = getCustomTemplateForFunction(paramSpec, "Delete")
@@ -2921,14 +3056,9 @@ func ResourceDeleteFunction(resourceTyp properties.ResourceType, names *NameProv
listAttributeVariant := properties.NewNameVariant(listAttribute)
- var resourceIsMap bool
- if resourceTyp == properties.ResourceEntryPlural {
- resourceIsMap = true
- }
-
data := map[string]interface{}{
+ "PluralType": paramSpec.TerraformProviderConfig.PluralType,
"HasEncryptedResources": paramSpec.HasEncryptedResources(),
- "ResourceIsMap": resourceIsMap,
"HasImports": len(paramSpec.Imports) > 0,
"EntryOrConfig": paramSpec.EntryOrConfig(),
"ListAttribute": listAttributeVariant,
@@ -3051,14 +3181,73 @@ func createImportStateStructSpecs(resourceTyp properties.ResourceType, names *Na
Tags: "`json:\"location\"`",
})
+ var resourceHasParent bool
+ if spec.ResourceXpathVariablesWithChecks(false) {
+ resourceHasParent = true
+ }
+
switch resourceTyp {
case properties.ResourceEntry:
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ fields = append(fields, importStateStructFieldSpec{
+ Name: parentParam.Name.CamelCase,
+ Type: "types.String",
+ Tags: fmt.Sprintf("`json:\"%s\"`", parentParam.Name.Underscore),
+ })
+ }
+
fields = append(fields, importStateStructFieldSpec{
Name: "Name",
Type: "types.String",
Tags: "`json:\"name\"`",
})
- case properties.ResourceEntryPlural, properties.ResourceUuid:
+ case properties.ResourceEntryPlural:
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ fields = append(fields, importStateStructFieldSpec{
+ Name: parentParam.Name.CamelCase,
+ Type: "types.String",
+ Tags: fmt.Sprintf("`json:\"%s\"`", parentParam.Name.Underscore),
+ })
+ } else {
+ fields = append(fields, importStateStructFieldSpec{
+ Name: "Names",
+ Type: "types.List",
+ Tags: "`json:\"names\"`",
+ })
+ }
+ case properties.ResourceUuid:
fields = append(fields, importStateStructFieldSpec{
Name: "Names",
Type: "types.List",
@@ -3088,7 +3277,7 @@ func createImportStateStructSpecs(resourceTyp properties.ResourceType, names *Na
return specs
}
-func createImportStateMarshallerSpecs(resourceTyp properties.ResourceType, names *NameProvider, _ *properties.Normalization) []marshallerSpec {
+func createImportStateMarshallerSpecs(resourceTyp properties.ResourceType, names *NameProvider, spec *properties.Normalization) []marshallerSpec {
var specs []marshallerSpec
var fields []marshallerFieldSpec
@@ -3100,14 +3289,74 @@ func createImportStateMarshallerSpecs(resourceTyp properties.ResourceType, names
Tags: "`json:\"location\"`",
})
+ var resourceHasParent bool
+ if spec.ResourceXpathVariablesWithChecks(false) {
+ resourceHasParent = true
+ }
+
switch resourceTyp {
case properties.ResourceEntry:
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ fields = append(fields, marshallerFieldSpec{
+ Name: parentParam.Name,
+ Type: "string",
+ Tags: fmt.Sprintf("`json:\"%s\"`", parentParam.Name.Underscore),
+ })
+ }
+
fields = append(fields, marshallerFieldSpec{
Name: properties.NewNameVariant("name"),
Type: "string",
Tags: "`json:\"name\"`",
})
- case properties.ResourceEntryPlural, properties.ResourceUuid:
+ case properties.ResourceEntryPlural:
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ fields = append(fields, marshallerFieldSpec{
+ Name: parentParam.Name,
+ Type: "string",
+ Tags: fmt.Sprintf("`json:\"%s\"`", parentParam.Name.Underscore),
+ })
+ } else {
+ fields = append(fields, marshallerFieldSpec{
+ Name: properties.NewNameVariant("names"),
+ Type: "types.List",
+ StructName: "[]string",
+ Tags: "`json:\"names\"`",
+ })
+ }
+ case properties.ResourceUuid:
fields = append(fields, marshallerFieldSpec{
Name: properties.NewNameVariant("names"),
Type: "types.List",
@@ -3163,30 +3412,81 @@ func ResourceImportStateFunction(resourceTyp properties.ResourceType, names *Nam
type context struct {
StructName string
- ResourceIsMap bool
+ PluralType object.TerraformPluralType
ResourceIsList bool
HasPosition bool
HasEntryName bool
ListAttribute *properties.NameVariant
ListStructName string
PangoStructName string
+ HasParent bool
+ ParentAttribute *properties.NameVariant
}
data := context{
StructName: names.StructName,
}
+ var resourceHasParent bool
+ if spec.ResourceXpathVariablesWithChecks(false) {
+ resourceHasParent = true
+ }
+
switch resourceTyp {
case properties.ResourceEntry:
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ data.ParentAttribute = parentParam.Name
+ data.HasParent = true
+ }
data.HasEntryName = spec.HasEntryName()
case properties.ResourceEntryPlural:
- data.ResourceIsMap = true
- listAttribute := properties.NewNameVariant(spec.TerraformProviderConfig.PluralName)
- data.ListAttribute = listAttribute
- data.ListStructName = fmt.Sprintf("%sResource%sObject", names.StructName, listAttribute.CamelCase)
- data.PangoStructName = fmt.Sprintf("%s.Entry", names.PackageName)
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ data.PluralType = spec.TerraformProviderConfig.PluralType
+ data.ParentAttribute = parentParam.Name
+ data.HasParent = true
+
+ } else {
+ listAttribute := properties.NewNameVariant(spec.TerraformProviderConfig.PluralName)
+ data.PluralType = spec.TerraformProviderConfig.PluralType
+ data.ListAttribute = listAttribute
+ data.ListStructName = fmt.Sprintf("%sResource%sObject", names.StructName, listAttribute.CamelCase)
+ data.PangoStructName = fmt.Sprintf("%s.Entry", names.PackageName)
+ }
case properties.ResourceUuid, properties.ResourceUuidPlural:
data.ResourceIsList = true
+ data.PluralType = spec.TerraformProviderConfig.PluralType
listAttribute := properties.NewNameVariant(spec.TerraformProviderConfig.PluralName)
data.ListAttribute = properties.NewNameVariant(spec.TerraformProviderConfig.PluralName)
data.ListStructName = fmt.Sprintf("%sResource%sObject", names.StructName, listAttribute.CamelCase)
@@ -3213,6 +3513,8 @@ func RenderImportStateCreator(resourceTyp properties.ResourceType, names *NamePr
ListAttribute *properties.NameVariant
ListStructName string
ResourceType properties.ResourceType
+ HasParent bool
+ ParentAttribute *properties.NameVariant
}
data := context{
@@ -3222,12 +3524,58 @@ func RenderImportStateCreator(resourceTyp properties.ResourceType, names *NamePr
StructNamePrefix: names.StructName,
}
+ var resourceHasParent bool
+ if spec.ResourceXpathVariablesWithChecks(false) {
+ resourceHasParent = true
+ }
+
switch resourceTyp {
case properties.ResourceEntry:
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ data.HasParent = true
+ data.ParentAttribute = parentParam.Name
+ }
case properties.ResourceEntryPlural:
- listAttribute := properties.NewNameVariant(spec.TerraformProviderConfig.PluralName)
- data.ListAttribute = listAttribute
- data.ListStructName = fmt.Sprintf("%sResource%sObject", names.StructName, listAttribute.CamelCase)
+ if resourceHasParent {
+ var xpathVariable *object.PanosXpathVariable
+ for _, elt := range spec.PanosXpath.Variables {
+ if elt.Name == "parent" {
+ xpathVariable = &elt
+ }
+ }
+
+ if xpathVariable == nil {
+ panic("couldn't find parent variable for a child spec")
+ }
+
+ parentParam, err := spec.ParameterForPanosXpathVariable(*xpathVariable)
+ if err != nil {
+ panic(fmt.Sprintf("couldn't find matching param for xpath variable: %s", err.Error()))
+ }
+
+ data.HasParent = true
+ data.ParentAttribute = parentParam.Name
+ } else {
+ listAttribute := properties.NewNameVariant(spec.TerraformProviderConfig.PluralName)
+ data.ListAttribute = listAttribute
+ data.ListStructName = fmt.Sprintf("%sResource%sObject", names.StructName, listAttribute.CamelCase)
+ }
case properties.ResourceUuid, properties.ResourceUuidPlural:
listAttribute := properties.NewNameVariant(spec.TerraformProviderConfig.PluralName)
data.ListAttribute = listAttribute
diff --git a/pkg/translate/terraform_provider/template.go b/pkg/translate/terraform_provider/template.go
index eebe2d64..ceff823e 100644
--- a/pkg/translate/terraform_provider/template.go
+++ b/pkg/translate/terraform_provider/template.go
@@ -374,7 +374,9 @@ func (r *{{ resourceStructName }}) Configure(ctx context.Context, req {{ tfresou
resp.Diagnostics.AddError("Failed to configure SDK client", err.Error())
return
}
- r.manager = sdkmanager.NewImportableEntryObjectManager(r.client, {{ resourceSDKName }}.NewService(r.client), specifier, {{ resourceSDKName }}.SpecMatches)
+
+ batchSize := providerData.MultiConfigBatchSize
+ r.manager = sdkmanager.NewImportableEntryObjectManager(r.client, {{ resourceSDKName }}.NewService(r.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
{{- else if IsEntry }}
specifier, _, err := {{ resourceSDKName }}.Versioning(r.client.Versioning())
if err != nil {
@@ -382,7 +384,7 @@ func (r *{{ resourceStructName }}) Configure(ctx context.Context, req {{ tfresou
return
}
batchSize := providerData.MultiConfigBatchSize
- r.manager = sdkmanager.NewEntryObjectManager(r.client, {{ resourceSDKName }}.NewService(r.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
+ r.manager = sdkmanager.NewEntryObjectManager[*{{ resourceSDKName }}.Entry, {{ resourceSDKName }}.Location, *{{ resourceSDKName }}.Service](r.client, {{ resourceSDKName }}.NewService(r.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
{{- else if IsUuid }}
specifier, _, err := {{ resourceSDKName }}.Versioning(r.client.Versioning())
if err != nil {
@@ -390,7 +392,7 @@ func (r *{{ resourceStructName }}) Configure(ctx context.Context, req {{ tfresou
return
}
batchSize := providerData.MultiConfigBatchSize
- r.manager = sdkmanager.NewUuidObjectManager(r.client, {{ resourceSDKName }}.NewService(r.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
+ r.manager = sdkmanager.NewUuidObjectManager[*{{ resourceSDKName }}.Entry, {{ resourceSDKName }}.Location, *{{ resourceSDKName }}.Service](r.client, {{ resourceSDKName }}.NewService(r.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
{{- else if IsConfig }}
specifier, _, err := {{ resourceSDKName }}.Versioning(r.client.Versioning())
if err != nil {
@@ -407,6 +409,8 @@ func (r *{{ resourceStructName }}) Configure(ctx context.Context, req {{ tfresou
{{ RenderCopyFromPangoFunctions }}
+{{ RenderXpathComponentsGetter }}
+
{{- if FunctionSupported "Create" }}
func (r *{{ resourceStructName }}) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
{{ ResourceCreateFunction resourceStructName serviceName}}
@@ -493,6 +497,7 @@ type entryWithState struct {
StateIdx int
}
+{{ if eq .PluralType "map" }}
var elements map[string]{{ $resourceTFStructName }}
resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
if resp.Diagnostics.HasError() {
@@ -511,13 +516,38 @@ for name, elt := range elements {
entries[idx] = entry
idx++
}
+{{ else if or (eq .PluralType "list") (eq .PluralType "set") }}
+var elements []{{ $resourceTFStructName }}
+resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
+if resp.Diagnostics.HasError() {
+ return
+}
-created, err := r.manager.CreateMany(ctx, location, entries)
+entries := make([]*{{ $resourceSDKStructName }}, len(elements))
+for idx, elt := range elements {
+ var entry *{{ .resourceSDKName }}.{{ .EntryOrConfig }}
+ resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, {{ $ev }})...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ entry.Name = elt.Name.ValueString()
+ entries[idx] = entry
+}
+{{- end }}
+
+components, err := state.resourceXpathParentComponents()
+if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+}
+
+created, err := r.manager.CreateMany(ctx, location, components, entries)
if err != nil {
resp.Diagnostics.AddError("Failed to create new entries", err.Error())
return
}
+{{ if eq .PluralType "map" }}
for _, elt := range created {
if _, found := elements[elt.Name]; !found {
continue
@@ -536,6 +566,37 @@ resp.Diagnostics.Append(map_diags...)
if resp.Diagnostics.HasError() {
return
}
+{{ else if or (eq .PluralType "list") (eq .PluralType "set") }}
+elementsByName := make(map[string]int)
+for idx, elt := range elements {
+ elementsByName[elt.Name.ValueString()] = idx
+}
+
+for _, elt := range created {
+ idx, found := elementsByName[elt.Name]
+ if !found {
+ continue
+ }
+
+ var object {{ $resourceTFStructName }}
+ resp.Diagnostics.Append(object.CopyFromPango(ctx, elt, {{ $ev }})...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ elements[idx] = object
+}
+
+var list_diags diag.Diagnostics
+ {{ if eq .PluralType "list" }}
+state.{{ .ListAttribute.CamelCase }}, list_diags = types.ListValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), elements)
+ {{ else if eq .PluralType "set" }}
+state.{{ .ListAttribute.CamelCase }}, list_diags = types.SetValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), elements)
+ {{- end }}
+resp.Diagnostics.Append(list_diags...)
+if resp.Diagnostics.HasError() {
+ return
+}
+{{- end }}
{{- if .HasEncryptedResources }}
ev_map, ev_diags := types.MapValueFrom(ctx, types.StringType, ev)
@@ -591,14 +652,14 @@ for idx, elt := range elements {
entries[idx] = entry
}
-{{- if .ResourceIsMap }}
-processed, err := o.manager.CreateMany(ctx, location, entries)
+components, err := state.resourceXpathParentComponents()
if err != nil {
- resp.Diagnostics.AddError("Error during CreateMany() call", err.Error())
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
return
}
-{{- else if .Exhaustive }}
-processed, err := r.manager.CreateMany(ctx, location, entries, sdkmanager.Exhaustive, movement.PositionFirst{})
+
+{{- if .Exhaustive }}
+processed, err := r.manager.CreateMany(ctx, location, components, entries, sdkmanager.Exhaustive, movement.PositionFirst{})
if err != nil {
resp.Diagnostics.AddError("Error during CreateMany() call", err.Error())
return
@@ -610,33 +671,12 @@ if resp.Diagnostics.HasError() {
return
}
position := positionAttribute.CopyToPango()
-processed, err := r.manager.CreateMany(ctx, location, entries, sdkmanager.NonExhaustive, position)
+processed, err := r.manager.CreateMany(ctx, location, components, entries, sdkmanager.NonExhaustive, position)
if err != nil {
resp.Diagnostics.AddError("Error during CreateMany() call", err.Error())
return
}
{{- end }}
-
-
-{{- if .ResourceIsMap }}
-objects := make(map[string]{{ $resourceTFStructName }}, len(processed))
-for _, elt := range processed {
- var object {{ $resourceTFStructName }}
- copy_diags := object.CopyFromPango(ctx, elt, {{ $ev }})
- resp.Diagnostics.Append(copy_diags...)
- if resp.Diagnostics.HasError() {
- return
- }
- objects[elt.Name] = object
-}
-
-var map_diags diag.Diagnostics
-state.{{ .ListAttribute.CamelCase }}, map_diags = types.MapValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), objects)
-resp.Diagnostics.Append(list_diags...)
-if resp.Diagnostics.HasError() {
- return
-}
-{{- else }}
objects := make([]{{ $resourceTFStructName }}, len(processed))
for idx, elt := range processed {
var object {{ $resourceTFStructName }}
@@ -654,7 +694,6 @@ resp.Diagnostics.Append(list_diags...)
if resp.Diagnostics.HasError() {
return
}
-{{- end }}
{{- if .HasEncryptedResources }}
ev_map, ev_diags := types.MapValueFrom(ctx, types.StringType, ev)
@@ -720,17 +759,35 @@ const resourceCreateFunction = `
*/
// Perform the operation.
+
+ components, err := state.resourceXpathParentComponents()
+ if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+ }
+
{{- if .HasImports }}
var importLocation {{ .resourceSDKName }}.ImportLocation
{{ RenderImportLocationAssignment "state.Location" "importLocation" }}
- created, err := r.manager.Create(ctx, location, []{{ .resourceSDKName }}.ImportLocation{importLocation}, obj)
+ created, err := r.manager.Create(ctx, location, components, obj)
+ if err != nil {
+ resp.Diagnostics.AddError("Error in create", err.Error())
+ return
+ }
+
+ err = r.manager.ImportToLocations(ctx, location, []{{ .resourceSDKName }}.ImportLocation{importLocation}, obj.Name)
+ if err != nil {
+ resp.Diagnostics.AddError("Failed to import resource into location", err.Error())
+ return
+ }
{{- else }}
- created, err := r.manager.Create(ctx, location, obj)
-{{- end }}
+ created, err := r.manager.Create(ctx, location, components, obj)
if err != nil {
resp.Diagnostics.AddError("Error in create", err.Error())
return
}
+{{- end }}
+
resp.Diagnostics.Append(state.CopyFromPango(ctx, created, {{ $ev }})...)
if resp.Diagnostics.HasError() {
@@ -745,10 +802,6 @@ const resourceCreateFunction = `
}
{{- end }}
-{{- if .HasEntryName }}
- state.Name = types.StringValue(created.Name)
-{{- end }}
-
// Done.
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
@@ -800,6 +853,7 @@ if resp.Diagnostics.HasError() {
}
{{- end }}
+{{- if eq .PluralType "map" }}
elements := make(map[string]{{ $resourceTFStructName }})
resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
if len(elements) == 0 || resp.Diagnostics.HasError() {
@@ -816,8 +870,31 @@ for name, elt := range elements {
entry.Name = name
entries = append(entries, entry)
}
+{{- else if or (eq .PluralType "list") (eq .PluralType "set") }}
+var elements []{{ $resourceTFStructName }}
+resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
+if resp.Diagnostics.HasError() {
+ return
+}
+
+entries := make([]*{{ $resourceSDKStructName }}, 0, len(elements))
+for _, elt := range elements {
+ var entry *{{ $resourceSDKStructName }}
+ resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, {{ $ev }})...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ entries = append(entries, entry)
+}
+{{- end }}
-readEntries, err := o.manager.ReadMany(ctx, location, entries)
+components, err := state.resourceXpathParentComponents()
+if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+}
+
+readEntries, err := o.manager.ReadMany(ctx, location, components, entries)
if err != nil {
if errors.Is(err, sdkmanager.ErrObjectNotFound) {
resp.State.RemoveResource(ctx)
@@ -827,6 +904,7 @@ if err != nil {
return
}
+{{- if eq .PluralType "map" }}
objects := make(map[string]{{ $resourceTFStructName }})
for _, elt := range readEntries {
var object {{ $resourceTFStructName }}
@@ -836,13 +914,44 @@ for _, elt := range readEntries {
}
objects[elt.Name] = object
}
+{{- else if or (eq .PluralType "list") (eq .PluralType "set") }}
+objects := make([]{{ $resourceTFStructName }}, len(readEntries))
+for idx, elt := range readEntries {
+ var object {{ $resourceTFStructName }}
+ resp.Diagnostics.Append(object.CopyFromPango(ctx, elt, {{ $ev }})...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ objects[idx] = object
+}
+{{- end }}
+{{ if eq .PluralType "map" }}
var map_diags diag.Diagnostics
state.{{ .ListAttribute.CamelCase }}, map_diags = types.MapValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), objects)
resp.Diagnostics.Append(map_diags...)
if resp.Diagnostics.HasError() {
return
}
+{{- else if eq .PluralType "list" }}
+var list_diags diag.Diagnostics
+state.{{ .ListAttribute.CamelCase }}, list_diags = types.ListValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), objects)
+resp.Diagnostics.Append(list_diags...)
+if resp.Diagnostics.HasError() {
+ return
+}
+{{- else if eq .PluralType "set" }}
+var list_diags diag.Diagnostics
+state.{{ .ListAttribute.CamelCase }}, list_diags = types.SetValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), objects)
+resp.Diagnostics.Append(list_diags...)
+if resp.Diagnostics.HasError() {
+ return
+}
+{{- end }}
+
+{{- if .ResourceXpathVariablesWithChecks }}
+{{ AttributesFromXpathComponents "state" }}
+{{- end }}
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
`
@@ -995,12 +1104,16 @@ const resourceReadFunction = `
{{- end }}
})
+ components, err := savestate.resourceXpathParentComponents()
+ if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+ }
- // Perform the operation.
{{- if .HasEntryName }}
- object, err := o.manager.Read(ctx, location, savestate.Name.ValueString())
+ object, err := o.manager.Read(ctx, location, components, savestate.Name.ValueString())
{{- else }}
- object, err := o.manager.Read(ctx, location)
+ object, err := o.manager.Read(ctx, location, components)
{{- end }}
if err != nil {
if errors.Is(err, sdkmanager.ErrObjectNotFound) {
@@ -1032,6 +1145,7 @@ const resourceReadFunction = `
resp.Diagnostics.Append(ev_diags...)
{{- end }}
+{{ AttributesFromXpathComponents "state" }}
// Done.
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
@@ -1063,6 +1177,17 @@ tflog.Info(ctx, "performing resource update", map[string]any{
"function": "Update",
})
+{{ $ev := "nil" }}
+{{ if .HasEncryptedResources }}
+ {{- $ev = "&ev" }}
+ev := make(map[string]types.String, len(state.EncryptedValues.Elements()))
+resp.Diagnostics.Append(state.EncryptedValues.ElementsAs(ctx, &ev, false)...)
+if resp.Diagnostics.HasError() {
+ return
+}
+{{- end }}
+
+{{ if eq .PluralType "map" }}
var elements map[string]{{ $resourceTFStructName }}
resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
if resp.Diagnostics.HasError() {
@@ -1072,17 +1197,40 @@ if resp.Diagnostics.HasError() {
stateEntries := make([]*{{ $resourceSDKStructName }}, len(elements))
idx := 0
for name, elt := range elements {
+ var entry *{{ .resourceSDKName }}.{{ .EntryOrConfig }}
+ resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, {{ $ev }})...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ entry.Name = name
+ stateEntries[idx] = entry
+ idx++
+}
+{{ else if or (eq .PluralType "list") (eq .PluralType "set") }}
+var elements []{{ $resourceTFStructName }}
+resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
+if resp.Diagnostics.HasError() {
+ return
+}
+
+stateEntries := make([]*{{ $resourceSDKStructName }}, len(elements))
+for idx, elt := range elements {
var entry *{{ $resourceSDKStructName }}
resp.Diagnostics.Append(elt.CopyToPango(ctx, &entry, nil)...)
if resp.Diagnostics.HasError() {
return
}
- entry.Name = name
stateEntries[idx] = entry
- idx++
}
+{{- end }}
-existing, err := r.manager.ReadMany(ctx, location, stateEntries)
+components, err := state.resourceXpathParentComponents()
+if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+}
+
+existing, err := r.manager.ReadMany(ctx, location, components, stateEntries)
if err != nil && !errors.Is(err, sdkmanager.ErrObjectNotFound) {
resp.Diagnostics.AddError("Error while reading entries from the server", err.Error())
return
@@ -1098,6 +1246,7 @@ if resp.Diagnostics.HasError() {
return
}
+{{ if eq .PluralType "map" }}
planEntries := make([]*{{ $resourceSDKStructName }}, len(elements))
idx = 0
for name, elt := range elements {
@@ -1111,13 +1260,26 @@ for name, elt := range elements {
planEntries[idx] = entry
idx++
}
+{{ else if or (eq .PluralType "list") (eq .PluralType "set") }}
+var planEntries []*{{ $resourceSDKStructName }}
+for _, elt := range elements {
+ existingEntry, _ := existingEntriesByName[elt.Name.ValueString()]
+ resp.Diagnostics.Append(elt.CopyToPango(ctx, &existingEntry, nil)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ planEntries = append(planEntries, existingEntry)
+}
+{{- end }}
-processed, err := r.manager.UpdateMany(ctx, location, stateEntries, planEntries)
+processed, err := r.manager.UpdateMany(ctx, location, components, stateEntries, planEntries)
if err != nil {
resp.Diagnostics.AddError("Error while updating entries", err.Error())
return
}
+{{- if eq .PluralType "map" }}
objects := make(map[string]*{{ $resourceTFStructName }}, len(processed))
for _, elt := range processed {
var object {{ $resourceTFStructName }}
@@ -1129,9 +1291,27 @@ for _, elt := range processed {
objects[elt.Name] = &object
}
+{{- else if or (eq .PluralType "list") (eq .PluralType "set") }}
+objects := make([]*{{ $resourceTFStructName }}, len(processed))
+for idx, elt := range processed {
+ var object {{ $resourceTFStructName }}
+ resp.Diagnostics.Append(object.CopyFromPango(ctx, elt, {{ $ev }})...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ objects[idx] = &object
+}
+{{- end }}
var list_diags diag.Diagnostics
+{{ if eq .PluralType "map" }}
plan.{{ .ListAttribute.CamelCase }}, list_diags = types.MapValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), objects)
+{{ else if eq .PluralType "list" }}
+plan.{{ .ListAttribute.CamelCase }}, list_diags = types.ListValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), objects)
+{{ else if eq .PluralType "set" }}
+plan.{{ .ListAttribute.CamelCase }}, list_diags = types.SetValueFrom(ctx, state.getTypeFor("{{ .ListAttribute.Underscore }}"), objects)
+{{- end }}
resp.Diagnostics.Append(list_diags...)
if resp.Diagnostics.HasError() {
return
@@ -1214,7 +1394,13 @@ for idx, elt := range elements {
planEntries[idx] = entry
}
-processed, err := r.manager.UpdateMany(ctx, location, stateEntries, planEntries, {{ $exhaustive }}, position)
+components, err := state.resourceXpathParentComponents()
+if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+}
+
+processed, err := r.manager.UpdateMany(ctx, location, components, stateEntries, planEntries, {{ $exhaustive }}, position)
if err != nil {
resp.Diagnostics.AddError("Failed to udpate entries", err.Error())
}
@@ -1275,10 +1461,16 @@ const resourceUpdateFunction = `
return
}
+ components, err := state.resourceXpathParentComponents()
+ if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+ }
+
{{- if .HasEntryName }}
- obj, err := r.manager.Read(ctx, location, plan.Name.ValueString())
+ obj, err := r.manager.Read(ctx, location, components, plan.Name.ValueString())
{{- else }}
- obj, err := r.manager.Read(ctx, location)
+ obj, err := r.manager.Read(ctx, location, components)
{{- end }}
if err != nil {
resp.Diagnostics.AddError("Error in update", err.Error())
@@ -1290,12 +1482,17 @@ const resourceUpdateFunction = `
return
}
- // Perform the operation.
-{{- if .HasEntryName }}
- updated, err := r.manager.Update(ctx, location, obj, obj.Name)
-{{- else }}
- updated, err := r.manager.Update(ctx, location, obj)
-{{- end }}
+ components, err = plan.resourceXpathParentComponents()
+ if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+ }
+
+{{ if .HasEntryName }}
+ updated, err := r.manager.Update(ctx, location, components, obj, obj.Name)
+{{ else }}
+ updated, err := r.manager.Update(ctx, location, components, obj)
+{{ end }}
if err != nil {
resp.Diagnostics.AddError("Error in update", err.Error())
return
@@ -1341,13 +1538,13 @@ tflog.Info(ctx, "performing resource delete", map[string]any{
"function": "Delete",
})
-{{- if .ResourceIsMap }}
+{{- if eq .PluralType "map" }}
elements := make(map[string]{{ $resourceTFStructName }}, len(state.{{ .ListAttribute.CamelCase }}.Elements()))
resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
if resp.Diagnostics.HasError() {
return
}
-{{- else }}
+{{- else if or (eq .PluralType "list") (eq .PluralType "set") }}
var elements []{{ $resourceTFStructName }}
resp.Diagnostics.Append(state.{{ .ListAttribute.CamelCase }}.ElementsAs(ctx, &elements, false)...)
if resp.Diagnostics.HasError() {
@@ -1359,22 +1556,28 @@ var location {{ .resourceSDKName }}.Location
{{ RenderLocationsStateToPango "state.Location" "location" }}
var names []string
-{{- if .ResourceIsMap }}
+{{- if eq .PluralType "map" }}
for name, _ := range elements {
names = append(names, name)
}
-{{- else }}
+{{- else if or (eq .PluralType "list") (eq .PluralType "set") }}
for _, elt := range elements {
names = append(names, elt.Name.ValueString())
}
{{- end }}
-{{- if .ResourceIsMap }}
-err := r.manager.Delete(ctx, location, names)
-{{- else if .Exhaustive }}
-err := r.manager.Delete(ctx, location, names, sdkmanager.Exhaustive)
+components, err := state.resourceXpathParentComponents()
+if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+}
+
+{{- if eq .Exhaustive "exhaustive" }}
+err = r.manager.Delete(ctx, location, components, names, sdkmanager.Exhaustive)
+{{- else if eq .Exhaustive "non-exhaustive" }}
+err = r.manager.Delete(ctx, location, components, names, sdkmanager.NonExhaustive)
{{- else }}
-err := r.manager.Delete(ctx, location, names, sdkmanager.NonExhaustive)
+err = r.manager.Delete(ctx, location, components, names)
{{- end }}
if err != nil {
resp.Diagnostics.AddError("error while deleting entries", err.Error())
@@ -1410,15 +1613,26 @@ const resourceDeleteFunction = `
{{ RenderLocationsStateToPango "state.Location" "location" }}
{{- if .HasEntryName }}
+ components, err := state.resourceXpathParentComponents()
+ if err != nil {
+ resp.Diagnostics.AddError("Error creating resource xpath", err.Error())
+ return
+ }
{{- if .HasImports }}
var importLocation {{ .resourceSDKName }}.ImportLocation
{{ RenderImportLocationAssignment "state.Location" "importLocation" }}
- err := r.manager.Delete(ctx, location, []{{ .resourceSDKName }}.ImportLocation{importLocation}, []string{state.Name.ValueString()}, sdkmanager.NonExhaustive)
+ err = r.manager.UnimportFromLocations(ctx, location, []{{ .resourceSDKName }}.ImportLocation{importLocation}, state.Name.ValueString())
+ if err != nil {
+ resp.Diagnostics.AddError("Error in delete", err.Error())
+ return
+ }
+ err = r.manager.Delete(ctx, location, []{{ .resourceSDKName }}.ImportLocation{importLocation}, components, []string{state.Name.ValueString()})
{{- else }}
- err := r.manager.Delete(ctx, location, []string{state.Name.ValueString()})
+ err = r.manager.Delete(ctx, location, components, []string{state.Name.ValueString()})
{{- end }}
if err != nil && !errors.Is(err, sdkmanager.ErrObjectNotFound) {
resp.Diagnostics.AddError("Error in delete", err.Error())
+ return
}
{{- else }}
@@ -1436,6 +1650,7 @@ const resourceDeleteFunction = `
err := r.manager.Delete(ctx, location, obj)
if err != nil && errors.Is(err, sdkmanager.ErrObjectNotFound) {
resp.Diagnostics.AddError("Error in delete", err.Error())
+ return
}
{{- end }}
`
@@ -1608,6 +1823,25 @@ func {{ .FuncName }}(ctx context.Context, resource types.Object) ([]byte, error)
Name: name,
}
{{- else if eq .ResourceType "entry-plural" }}
+ {{- if .HasParent }}
+ parentAttr, ok := attrs["{{ .ParentAttribute.Underscore }}"]
+ if !ok {
+ return nil, fmt.Errorf("{{ .ParentAttribute.Underscore }} attribute missing")
+ }
+
+ var parent types.String
+ switch value := parentAttr.(type) {
+ case types.String:
+ parent = value
+ default:
+ return nil, fmt.Errorf("{{ .ParentAttribute.Underscore }} expected to be a map")
+ }
+
+ importStruct := {{ .StructNamePrefix }}ImportState{
+ Location: location,
+ {{ .ParentAttribute.CamelCase }}: parent,
+ }
+ {{- else }}
itemsAttr, ok := attrs["{{ .ListAttribute.Underscore }}"]
if !ok {
return nil, fmt.Errorf("{{ .ListAttribute.Underscore }} attribute missing")
@@ -1642,6 +1876,7 @@ func {{ .FuncName }}(ctx context.Context, resource types.Object) ([]byte, error)
Location: location,
Names: namesObj,
}
+ {{- end }}
{{- else if or (eq .ResourceType "uuid") }}
itemsAttr, ok := attrs["{{ .ListAttribute.Underscore }}"]
if !ok {
@@ -1749,8 +1984,12 @@ const resourceImportStateFunctionTmpl = `
if resp.Diagnostics.HasError() {
return
}
-
-{{- if .ResourceIsMap }}
+{{- if .HasParent }}
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("{{ .ParentAttribute.Underscore }}"), obj.{{ .ParentAttribute.CamelCase }})...)
+ {{- if eq .PluralType "" }}
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("name"), obj.Name)...)
+ {{- end }}
+{{- else if eq .PluralType "map" }}
names := make(map[string]*{{ .ListStructName }})
var objectNames []string
@@ -1767,7 +2006,7 @@ const resourceImportStateFunctionTmpl = `
names[elt] = object
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("{{ .ListAttribute.Underscore }}"), names)...)
-{{- else if .ResourceIsList }}
+{{- else if eq .PluralType "list" }}
{{- if .HasPosition }}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("position"), obj.Position)...)
if resp.Diagnostics.HasError() {
@@ -1851,6 +2090,8 @@ type {{ dataSourceStructName }}Filter struct {
{{ RenderCopyFromPangoFunctions }}
+{{ RenderXpathComponentsGetter }}
+
{{ RenderDataSourceSchema }}
{{- if HasLocations }}
@@ -1886,7 +2127,8 @@ func (d *{{ dataSourceStructName }}) Configure(_ context.Context, req datasource
resp.Diagnostics.AddError("Failed to configure SDK client", err.Error())
return
}
- d.manager = sdkmanager.NewImportableEntryObjectManager(d.client, {{ resourceSDKName }}.NewService(d.client), specifier, {{ resourceSDKName }}.SpecMatches)
+ batchSize := providerData.MultiConfigBatchSize
+ d.manager = sdkmanager.NewImportableEntryObjectManager(d.client, {{ resourceSDKName }}.NewService(d.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
{{- else if IsEntry }}
specifier, _, err := {{ resourceSDKName }}.Versioning(d.client.Versioning())
if err != nil {
@@ -1894,7 +2136,7 @@ func (d *{{ dataSourceStructName }}) Configure(_ context.Context, req datasource
return
}
batchSize := providerData.MultiConfigBatchSize
- d.manager = sdkmanager.NewEntryObjectManager(d.client, {{ resourceSDKName }}.NewService(d.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
+ d.manager = sdkmanager.NewEntryObjectManager[*{{ resourceSDKName }}.Entry, {{ resourceSDKName }}.Location, *{{ resourceSDKName }}.Service](d.client, {{ resourceSDKName }}.NewService(d.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
{{- else if IsUuid }}
specifier, _, err := {{ resourceSDKName }}.Versioning(d.client.Versioning())
if err != nil {
@@ -1902,7 +2144,7 @@ func (d *{{ dataSourceStructName }}) Configure(_ context.Context, req datasource
return
}
batchSize := providerData.MultiConfigBatchSize
- d.manager = sdkmanager.NewUuidObjectManager(d.client, {{ resourceSDKName }}.NewService(d.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
+ d.manager = sdkmanager.NewUuidObjectManager[*{{ resourceSDKName }}.Entry, {{ resourceSDKName }}.Location, *{{ resourceSDKName }}.Service](d.client, {{ resourceSDKName }}.NewService(d.client), batchSize, specifier, {{ resourceSDKName }}.SpecMatches)
{{- else if IsConfig }}
specifier, _, err := {{ resourceSDKName }}.Versioning(d.client.Versioning())
if err != nil {
diff --git a/pkg/translate/terraform_provider/terraform_provider_file.go b/pkg/translate/terraform_provider/terraform_provider_file.go
index d1645882..272bb231 100644
--- a/pkg/translate/terraform_provider/terraform_provider_file.go
+++ b/pkg/translate/terraform_provider/terraform_provider_file.go
@@ -159,6 +159,16 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper
panic("unreachable")
},
+ "IsResourcePlural": func() bool {
+ switch resourceTyp {
+ case properties.ResourceEntryPlural, properties.ResourceUuid, properties.ResourceUuidPlural:
+ return true
+ case properties.ResourceEntry, properties.ResourceConfig, properties.ResourceCustom:
+ return false
+ }
+
+ panic("unreachable")
+ },
"tfresourcepkg": func() string {
if spec.TerraformProviderConfig.Ephemeral {
return "ephemeral"
@@ -188,6 +198,9 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper
"RenderCopyFromPangoFunctions": func() (string, error) {
return RenderCopyFromPangoFunctions(resourceTyp, names.PackageName, names.ResourceStructName, spec)
},
+ "RenderXpathComponentsGetter": func() (string, error) {
+ return RenderXpathComponentsGetter(names.ResourceStructName, spec)
+ },
"ResourceCreateFunction": func(structName string, serviceName string) (string, error) {
return ResourceCreateFunction(resourceTyp, names, serviceName, spec, terraformProvider, names.PackageName)
},
@@ -234,6 +247,7 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper
if !spec.TerraformProviderConfig.SkipResource {
terraformProvider.ImportManager.AddStandardImport("context", "")
terraformProvider.ImportManager.AddSdkImport("github.com/PaloAltoNetworks/pango", "")
+
if spec.TerraformProviderConfig.ResourceType != properties.TerraformResourceCustom {
terraformProvider.ImportManager.AddOtherImport("github.com/PaloAltoNetworks/terraform-provider-panos/internal/manager", "sdkmanager")
}
@@ -256,6 +270,11 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper
case properties.ResourceCustom, properties.ResourceConfig:
}
+ switch resourceTyp {
+ case properties.ResourceEntry, properties.ResourceConfig:
+ case properties.ResourceEntryPlural, properties.ResourceUuid, properties.ResourceUuidPlural, properties.ResourceCustom:
+ }
+
// Generate Resource with entry style
terraformProvider.ImportManager.AddStandardImport("fmt", "")
@@ -283,6 +302,11 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper
terraformProvider.ImportManager.AddHashicorpImport("github.com/hashicorp/terraform-plugin-log/tflog", "")
}
+ if spec.ResourceXpathVariablesWithChecks(false) {
+ terraformProvider.ImportManager.AddStandardImport("strings", "")
+ terraformProvider.ImportManager.AddSdkImport("github.com/PaloAltoNetworks/pango/util", "pangoutil")
+ }
+
err := g.generateTerraformEntityTemplate(resourceTyp, schemaTyp, names, spec, terraformProvider, resourceObj, funcMap)
if err != nil {
return err
@@ -302,6 +326,7 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper
case properties.ResourceEntryPlural, properties.ResourceUuid:
case properties.ResourceUuidPlural, properties.ResourceCustom:
}
+
conditionallyAddValidators(terraformProvider.ImportManager, spec)
conditionallyAddModifiers(terraformProvider.ImportManager, spec)
conditionallyAddDefaults(terraformProvider.ImportManager, spec.Spec)
@@ -322,6 +347,11 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(resourceTyp proper
terraformProvider.ImportManager.AddHashicorpImport("github.com/hashicorp/terraform-plugin-log/tflog", "")
}
+ if spec.ResourceXpathVariablesWithChecks(false) {
+ terraformProvider.ImportManager.AddStandardImport("strings", "")
+ terraformProvider.ImportManager.AddSdkImport("github.com/PaloAltoNetworks/pango/util", "pangoutil")
+ }
+
err := g.generateTerraformEntityTemplate(resourceTyp, schemaTyp, names, spec, terraformProvider, resourceObj, funcMap)
if err != nil {
return err
@@ -355,8 +385,18 @@ func (g *GenerateTerraformProvider) GenerateTerraformDataSource(resourceTyp prop
names := NewNameProvider(spec, resourceTyp)
funcMap := template.FuncMap{
- "GoSDKSkipped": func() bool { return spec.GoSdkSkip },
- "IsEntry": func() bool { return spec.HasEntryName() && !spec.HasEntryUuid() },
+ "GoSDKSkipped": func() bool { return spec.GoSdkSkip },
+ "IsEntry": func() bool { return spec.HasEntryName() && !spec.HasEntryUuid() },
+ "IsResourcePlural": func() bool {
+ switch resourceTyp {
+ case properties.ResourceEntryPlural, properties.ResourceUuid, properties.ResourceUuidPlural:
+ return true
+ case properties.ResourceEntry, properties.ResourceConfig, properties.ResourceCustom:
+ return false
+ }
+
+ panic("unreachable")
+ },
"HasImports": func() bool { return len(spec.Imports) > 0 },
"HasLocations": func() bool { return len(spec.Locations) > 0 },
"IsCustom": func() bool { return spec.TerraformProviderConfig.ResourceType == properties.TerraformResourceCustom },
@@ -383,6 +423,9 @@ func (g *GenerateTerraformProvider) GenerateTerraformDataSource(resourceTyp prop
"RenderCopyFromPangoFunctions": func() (string, error) {
return RenderCopyFromPangoFunctions(resourceTyp, names.PackageName, names.DataSourceStructName, spec)
},
+ "RenderXpathComponentsGetter": func() (string, error) {
+ return RenderXpathComponentsGetter(names.DataSourceStructName, spec)
+ },
"RenderDataSourceStructs": func() (string, error) { return RenderDataSourceStructs(resourceTyp, names, spec) },
"RenderDataSourceSchema": func() (string, error) {
return RenderDataSourceSchema(resourceTyp, names, spec, terraformProvider.ImportManager)
diff --git a/pkg/translate/translate_suite_test.go b/pkg/translate/translate_suite_test.go
new file mode 100644
index 00000000..05beb9eb
--- /dev/null
+++ b/pkg/translate/translate_suite_test.go
@@ -0,0 +1,18 @@
+package translate_test
+
+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")
+}
diff --git a/pkg/version/version.go b/pkg/version/version.go
index f0f610f9..8e937680 100644
--- a/pkg/version/version.go
+++ b/pkg/version/version.go
@@ -14,6 +14,15 @@ type Version struct {
Hotfix string
}
+func MustNewVersionFromString(version string) *Version {
+ result, err := NewVersionFromString(version)
+ if err != nil {
+ panic(err)
+ }
+
+ return &result
+}
+
// NewVersionFromString creates a new Version value from a given string
func NewVersionFromString(version string) (Version, error) {
parts := strings.Split(version, ".")
diff --git a/specs/device/adminrole.yaml b/specs/device/adminrole.yaml
index 4e73e35b..7df47acc 100644
--- a/specs/device/adminrole.yaml
+++ b/specs/device/adminrole.yaml
@@ -14,8 +14,10 @@ go_sdk_config:
package:
- device
- adminrole
-xpath_suffix:
-- admin-role
+panos_xpath:
+ path:
+ - admin-role
+ vars: []
locations:
- name: template
xpath:
@@ -2338,6 +2340,27 @@ spec:
- value: disable
description: ''
required: false
+ - name: dhcp-syslog-server
+ type: enum
+ profiles:
+ - xpath:
+ - dhcp-syslog-server
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators:
+ - type: values
+ spec:
+ values:
+ - enable
+ - read-only
+ - disable
+ spec:
+ values:
+ - value: enable
+ - value: read-only
+ - value: disable
+ description: ''
+ required: false
- name: dynamic-updates
type: enum
profiles:
@@ -3339,27 +3362,6 @@ spec:
- value: disable
description: ''
required: false
- - name: dhcp-syslog-server
- type: enum
- profiles:
- - xpath:
- - dhcp-syslog-server
- min_version: 11.0.2
- max_version: 11.0.3
- validators:
- - type: values
- spec:
- values:
- - enable
- - read-only
- - disable
- spec:
- values:
- - value: enable
- - value: read-only
- - value: disable
- description: ''
- required: false
variants: []
description: ''
required: false
@@ -5125,11 +5127,13 @@ spec:
- value: disable
description: ''
required: false
- - name: virtual-routers
+ - name: secure-web-gateway
type: enum
profiles:
- xpath:
- - virtual-routers
+ - secure-web-gateway
+ min_version: 11.0.2
+ max_version: 11.0.3
validators:
- type: values
spec:
@@ -5144,11 +5148,11 @@ spec:
- value: disable
description: ''
required: false
- - name: virtual-wires
+ - name: virtual-routers
type: enum
profiles:
- xpath:
- - virtual-wires
+ - virtual-routers
validators:
- type: values
spec:
@@ -5163,11 +5167,11 @@ spec:
- value: disable
description: ''
required: false
- - name: vlans
+ - name: virtual-wires
type: enum
profiles:
- xpath:
- - vlans
+ - virtual-wires
validators:
- type: values
spec:
@@ -5182,11 +5186,11 @@ spec:
- value: disable
description: ''
required: false
- - name: zones
+ - name: vlans
type: enum
profiles:
- xpath:
- - zones
+ - vlans
validators:
- type: values
spec:
@@ -5201,13 +5205,11 @@ spec:
- value: disable
description: ''
required: false
- - name: secure-web-gateway
+ - name: zones
type: enum
profiles:
- xpath:
- - secure-web-gateway
- min_version: 11.0.2
- max_version: 11.0.3
+ - zones
validators:
- type: values
spec:
@@ -6416,11 +6418,13 @@ spec:
validators: []
spec:
params:
- - name: partial-save
+ - name: object-level-changes
type: enum
profiles:
- xpath:
- - partial-save
+ - object-level-changes
+ min_version: 11.0.2
+ max_version: 11.0.3
validators:
- type: values
spec:
@@ -6433,11 +6437,11 @@ spec:
- value: disable
description: ''
required: false
- - name: save-for-other-admins
+ - name: partial-save
type: enum
profiles:
- xpath:
- - save-for-other-admins
+ - partial-save
validators:
- type: values
spec:
@@ -6450,13 +6454,11 @@ spec:
- value: disable
description: ''
required: false
- - name: object-level-changes
+ - name: save-for-other-admins
type: enum
profiles:
- xpath:
- - object-level-changes
- min_version: 11.0.2
- max_version: 11.0.3
+ - save-for-other-admins
validators:
- type: values
spec:
@@ -6956,11 +6958,13 @@ spec:
- value: disable
description: ''
required: false
- - name: zones
+ - name: sdwan-interface-profiles
type: enum
profiles:
- xpath:
- - zones
+ - sdwan-interface-profiles
+ min_version: 11.0.2
+ max_version: 11.0.3
validators:
- type: values
spec:
@@ -6975,13 +6979,11 @@ spec:
- value: disable
description: ''
required: false
- - name: sdwan-interface-profiles
+ - name: zones
type: enum
profiles:
- xpath:
- - sdwan-interface-profiles
- min_version: 11.0.2
- max_version: 11.0.3
+ - zones
validators:
- type: values
spec:
@@ -8336,6 +8338,27 @@ spec:
- value: disable
description: ''
required: false
+ - name: dhcp-syslog-server
+ type: enum
+ profiles:
+ - xpath:
+ - dhcp-syslog-server
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators:
+ - type: values
+ spec:
+ values:
+ - enable
+ - read-only
+ - disable
+ spec:
+ values:
+ - value: enable
+ - value: read-only
+ - value: disable
+ description: ''
+ required: false
- name: local-user-database
type: object
profiles:
@@ -9047,27 +9070,6 @@ spec:
- value: disable
description: ''
required: false
- - name: dhcp-syslog-server
- type: enum
- profiles:
- - xpath:
- - dhcp-syslog-server
- min_version: 11.0.2
- max_version: 11.0.3
- validators:
- - type: values
- spec:
- values:
- - enable
- - read-only
- - disable
- spec:
- values:
- - value: enable
- - value: read-only
- - value: disable
- description: ''
- required: false
variants: []
description: ''
required: false
@@ -11319,11 +11321,13 @@ spec:
validators: []
spec:
params:
- - name: partial-save
+ - name: object-level-changes
type: enum
profiles:
- xpath:
- - partial-save
+ - object-level-changes
+ min_version: 11.0.2
+ max_version: 11.0.3
validators:
- type: values
spec:
@@ -11336,11 +11340,11 @@ spec:
- value: disable
description: ''
required: false
- - name: save-for-other-admins
+ - name: partial-save
type: enum
profiles:
- xpath:
- - save-for-other-admins
+ - partial-save
validators:
- type: values
spec:
@@ -11353,13 +11357,11 @@ spec:
- value: disable
description: ''
required: false
- - name: object-level-changes
+ - name: save-for-other-admins
type: enum
profiles:
- xpath:
- - object-level-changes
- min_version: 11.0.2
- max_version: 11.0.3
+ - save-for-other-admins
validators:
- type: values
spec:
diff --git a/specs/device/api_key.yaml b/specs/device/api_key.yaml
index 45e806d2..f2501955 100644
--- a/specs/device/api_key.yaml
+++ b/specs/device/api_key.yaml
@@ -11,7 +11,8 @@ terraform_provider_config:
go_sdk_config:
skip: true
package: ["api_key"]
-xpath_suffix: ["api-key"]
+panos_xpath:
+ path: ["api-key"]
locations: []
entries: []
imports: []
diff --git a/specs/device/dns.yaml b/specs/device/dns.yaml
index 65a622ce..7b985531 100644
--- a/specs/device/dns.yaml
+++ b/specs/device/dns.yaml
@@ -15,7 +15,9 @@ go_sdk_config:
- device
- services
- dns
-xpath_suffix: []
+panos_xpath:
+ path: []
+ vars: []
locations:
- name: system
xpath:
diff --git a/specs/device/dynamic-updates.yaml b/specs/device/dynamic-updates.yaml
index b05f956d..1f7d1a0e 100644
--- a/specs/device/dynamic-updates.yaml
+++ b/specs/device/dynamic-updates.yaml
@@ -14,7 +14,9 @@ go_sdk_config:
package:
- device
- dynamicupdates
-xpath_suffix: []
+panos_xpath:
+ path: []
+ vars: []
locations:
- name: system
xpath:
@@ -204,6 +206,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -245,6 +248,7 @@ spec:
variants: []
description: Every hour
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -256,6 +260,7 @@ spec:
variants: []
description: No schedule
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -324,6 +329,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -409,6 +415,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -420,6 +427,7 @@ spec:
variants: []
description: No schedule
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -488,6 +496,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -551,6 +560,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -592,6 +602,7 @@ spec:
variants: []
description: Every hour
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -603,6 +614,7 @@ spec:
variants: []
description: No schedule
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -671,6 +683,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -732,6 +745,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -773,6 +787,7 @@ spec:
variants: []
description: Every hour
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -784,6 +799,7 @@ spec:
variants: []
description: No schedule
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -852,6 +868,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -1042,6 +1059,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: every-30-mins
type: object
profiles:
@@ -1092,6 +1110,7 @@ spec:
variants: []
description: Every 0, 30 minutes past the hour
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -1142,6 +1161,7 @@ spec:
variants: []
description: Every hour
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -1153,6 +1173,7 @@ spec:
variants: []
description: No schedule
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -1230,6 +1251,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -1302,6 +1324,7 @@ spec:
variants: []
description: Every 15 minutes
required: false
+ variant_group_id: 0
- name: every-30-mins
type: object
profiles:
@@ -1343,6 +1366,7 @@ spec:
variants: []
description: Every 30 minutes
required: false
+ variant_group_id: 0
- name: every-5-mins
type: object
profiles:
@@ -1384,6 +1408,7 @@ spec:
variants: []
description: Every 5 minutes
required: false
+ variant_group_id: 0
- name: every-hour
type: object
profiles:
@@ -1425,6 +1450,7 @@ spec:
variants: []
description: Every hour
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -1436,6 +1462,7 @@ spec:
variants: []
description: No schedule
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -1508,6 +1535,7 @@ spec:
variants: []
description: Every 0, 15, 30, 45 minutes past the hour
required: false
+ variant_group_id: 0
- name: every-30-mins
type: object
profiles:
@@ -1558,6 +1586,7 @@ spec:
variants: []
description: Every 0, 30 minutes past the hour
required: false
+ variant_group_id: 0
- name: every-hour
type: object
profiles:
@@ -1608,6 +1637,7 @@ spec:
variants: []
description: Every 0 minutes past the hour
required: false
+ variant_group_id: 0
- name: every-min
type: object
profiles:
@@ -1645,6 +1675,7 @@ spec:
variants: []
description: Every minute
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -1656,6 +1687,7 @@ spec:
variants: []
description: No schedule
required: false
+ variant_group_id: 0
- name: real-time
type: object
profiles:
@@ -1667,6 +1699,7 @@ spec:
variants: []
description: Real-time Streaming
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
diff --git a/specs/device/ntp.yaml b/specs/device/ntp.yaml
index d08f1ba1..95db70f4 100644
--- a/specs/device/ntp.yaml
+++ b/specs/device/ntp.yaml
@@ -15,7 +15,9 @@ go_sdk_config:
- device
- services
- ntp
-xpath_suffix: []
+panos_xpath:
+ path: []
+ vars: []
locations:
- name: system
xpath:
diff --git a/specs/device/ssl-decrypt.yaml b/specs/device/ssl-decrypt.yaml
index dd597f2a..01361279 100644
--- a/specs/device/ssl-decrypt.yaml
+++ b/specs/device/ssl-decrypt.yaml
@@ -14,7 +14,9 @@ go_sdk_config:
package:
- device
- ssldecrypt
-xpath_suffix: []
+panos_xpath:
+ path: []
+ vars: []
locations:
- name: panorama
xpath:
@@ -213,6 +215,58 @@ spec:
type: string
description: List of disabled predefined exclude certificates.
required: false
+ - name: forward-trust-certificate-ecdsa
+ type: string
+ profiles:
+ - xpath:
+ - forward-trust-certificate
+ - ecdsa
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Forward trust ECDSA certificate.
+ required: false
+ - name: forward-trust-certificate-rsa
+ type: string
+ profiles:
+ - xpath:
+ - forward-trust-certificate
+ - rsa
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Forward trust RSA certificate.
+ required: false
+ - name: forward-untrust-certificate-ecdsa
+ type: string
+ profiles:
+ - xpath:
+ - forward-untrust-certificate
+ - ecdsa
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Forward untrust ECDSA certificate.
+ required: false
+ - name: forward-untrust-certificate-rsa
+ type: string
+ profiles:
+ - xpath:
+ - forward-untrust-certificate
+ - rsa
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Forward untrust RSA certificate.
+ required: false
- name: root-ca-exclude-list
type: list
profiles:
@@ -278,56 +332,4 @@ spec:
type: string
description: List of trusted root CAs.
required: false
- - name: forward-trust-certificate-ecdsa
- type: string
- profiles:
- - xpath:
- - forward-trust-certificate
- - ecdsa
- validators:
- - type: length
- spec:
- max: 63
- spec: {}
- description: Forward trust ECDSA certificate.
- required: false
- - name: forward-trust-certificate-rsa
- type: string
- profiles:
- - xpath:
- - forward-trust-certificate
- - rsa
- validators:
- - type: length
- spec:
- max: 63
- spec: {}
- description: Forward trust RSA certificate.
- required: false
- - name: forward-untrust-certificate-ecdsa
- type: string
- profiles:
- - xpath:
- - forward-untrust-certificate
- - ecdsa
- validators:
- - type: length
- spec:
- max: 63
- spec: {}
- description: Forward untrust ECDSA certificate.
- required: false
- - name: forward-untrust-certificate-rsa
- type: string
- profiles:
- - xpath:
- - forward-untrust-certificate
- - rsa
- validators:
- - type: length
- spec:
- max: 63
- spec: {}
- description: Forward untrust RSA certificate.
- required: false
variants: []
diff --git a/specs/network/ike-gateway.yaml b/specs/network/ike-gateway.yaml
index 89bb1ce1..bc31b7a8 100644
--- a/specs/network/ike-gateway.yaml
+++ b/specs/network/ike-gateway.yaml
@@ -6,724 +6,730 @@ terraform_provider_config:
resource_type: entry
resource_variants: []
suffix: ike_gateway
- plural_suffix: ''
- plural_name: ''
- plural_description: ''
+ plural_suffix: ""
+ plural_name: ""
+ plural_description: ""
go_sdk_config:
skip: false
package:
- - crypto
- - ike
- - gateway
-xpath_suffix:
-- network
-- ike
-- gateway
+ - crypto
+ - ike
+ - gateway
+panos_xpath:
+ path:
+ - network
+ - ike
+ - gateway
locations:
-- name: ngfw
- xpath:
- path:
- - config
- - devices
- - $ngfw_device
- vars:
- - name: ngfw_device
- description: The NGFW device
- required: false
- default: localhost.localdomain
- validators: []
- type: entry
- description: Located in a specific NGFW device
- devices:
- - ngfw
- validators: []
- required: false
- read_only: false
-- name: template
- xpath:
- path:
- - config
- - devices
- - $panorama_device
- - template
- - $template
- - config
- - devices
- - $ngfw_device
- vars:
- - name: panorama_device
- description: Specific Panorama device
- required: false
- default: localhost.localdomain
- validators: []
- type: entry
- - name: template
- description: Specific Panorama template
- required: true
- validators: []
- type: entry
- - name: ngfw_device
- description: The NGFW device
- required: false
- default: localhost.localdomain
- validators: []
- type: entry
- description: Located in a specific template
- devices:
- - panorama
- validators: []
- required: false
- read_only: false
-- name: template-stack
- xpath:
- path:
- - config
- - devices
- - $panorama_device
- - template-stack
- - $template_stack
- - config
- - devices
- - $ngfw_device
- vars:
- - name: panorama_device
- description: Specific Panorama device
- required: false
- default: localhost.localdomain
- validators: []
- type: entry
- - name: template_stack
- description: Specific Panorama template stack
- required: true
- validators: []
- type: entry
- - name: ngfw_device
- description: The NGFW device
- required: false
- default: localhost.localdomain
- validators: []
- type: entry
- description: Located in a specific template stack
- devices:
- - panorama
- validators: []
- required: false
- read_only: false
+ - name: ngfw
+ xpath:
+ path:
+ - config
+ - devices
+ - $ngfw_device
+ vars:
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ description: Located in a specific NGFW device
+ devices:
+ - ngfw
+ validators: []
+ required: false
+ read_only: false
+ - name: template
+ xpath:
+ path:
+ - config
+ - devices
+ - $panorama_device
+ - template
+ - $template
+ - config
+ - devices
+ - $ngfw_device
+ vars:
+ - name: panorama_device
+ description: Specific Panorama device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ - name: template
+ description: Specific Panorama template
+ required: true
+ validators: []
+ type: entry
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ description: Located in a specific template
+ devices:
+ - panorama
+ validators: []
+ required: false
+ read_only: false
+ - name: template-stack
+ xpath:
+ path:
+ - config
+ - devices
+ - $panorama_device
+ - template-stack
+ - $template_stack
+ - config
+ - devices
+ - $ngfw_device
+ vars:
+ - name: panorama_device
+ description: Specific Panorama device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ - name: template_stack
+ description: Specific Panorama template stack
+ required: true
+ validators: []
+ type: entry
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ description: Located in a specific template stack
+ devices:
+ - panorama
+ validators: []
+ required: false
+ read_only: false
entries:
-- name: name
- description: ''
- validators: []
+ - name: name
+ description: ""
+ validators: []
imports: []
spec:
params:
- - name: authentication
- type: object
- profiles:
- - xpath:
- - authentication
- validators: []
- spec:
- params: []
- variants:
- - name: certificate
- type: object
- profiles:
+ - name: authentication
+ type: object
+ profiles:
- xpath:
- - certificate
- validators: []
- spec:
- params:
- - name: allow-id-payload-mismatch
- type: bool
- profiles:
- - xpath:
- - allow-id-payload-mismatch
- validators: []
- spec: {}
- description: Permit peer identification and certificate payload identification
- mismatch
- required: false
- - name: certificate-profile
- type: string
+ - authentication
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: certificate
+ type: object
profiles:
- - xpath:
- - certificate-profile
+ - xpath:
+ - certificate
validators: []
- spec: {}
- description: Profile for certificate valdiation during IKE negotiation
+ spec:
+ params:
+ - name: allow-id-payload-mismatch
+ type: bool
+ profiles:
+ - xpath:
+ - allow-id-payload-mismatch
+ validators: []
+ spec: {}
+ description:
+ Permit peer identification and certificate payload identification
+ mismatch
+ required: false
+ - name: certificate-profile
+ type: string
+ profiles:
+ - xpath:
+ - certificate-profile
+ validators: []
+ spec: {}
+ description: Profile for certificate valdiation during IKE negotiation
+ required: false
+ - name: local-certificate
+ type: object
+ profiles:
+ - xpath:
+ - local-certificate
+ validators: []
+ spec:
+ params:
+ - name: hash-and-url
+ type: object
+ profiles:
+ - xpath:
+ - hash-and-url
+ validators: []
+ spec:
+ params:
+ - name: base-url
+ type: string
+ profiles:
+ - xpath:
+ - base-url
+ validators:
+ - type: length
+ spec:
+ max: 1024
+ spec: {}
+ description:
+ The host and directory part of URL for local certificates(http
+ only)
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Use hash-and-url for local certificate
+ required: false
+ variants: []
+ description: ""
+ required: false
+ - name: name
+ type: string
+ profiles:
+ - xpath:
+ - name
+ validators:
+ - type: length
+ spec:
+ max: 255
+ spec: {}
+ description: Local certificate name
+ required: false
+ variants: []
+ description: ""
+ required: false
+ - name: strict-validation-revocation
+ type: bool
+ profiles:
+ - xpath:
+ - strict-validation-revocation
+ validators: []
+ spec: {}
+ description: Enable strict validation of peer's extended key use
+ required: false
+ - name: use-management-as-source
+ type: bool
+ profiles:
+ - xpath:
+ - use-management-as-source
+ validators: []
+ spec: {}
+ description: Use management interface IP as source to retrieve http certificates
+ required: false
+ variants: []
+ description: Use RSA or ECDSA digital signature authentication
required: false
- - name: local-certificate
+ - name: pre-shared-key
type: object
profiles:
- - xpath:
- - local-certificate
+ - xpath:
+ - pre-shared-key
validators: []
spec:
params:
- - name: hash-and-url
- type: object
- profiles:
- - xpath:
- - hash-and-url
- validators: []
- spec:
- params:
- - name: base-url
- type: string
- profiles:
+ - name: key
+ type: string
+ profiles:
- xpath:
- - base-url
- validators:
+ - key
+ validators:
- type: length
spec:
- max: 1024
- spec: {}
- description: The host and directory part of URL for local certificates(http
- only)
- required: false
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: Use hash-and-url for local certificate
- required: false
- variants: []
- description: ''
- required: false
- - name: name
- type: string
- profiles:
- - xpath:
- - name
- validators:
- - type: length
- spec:
- max: 255
- spec: {}
- description: Local certificate name
- required: false
+ max: 255
+ spec: {}
+ description: the string used as pre-shared key
+ required: false
variants: []
- description: ''
+ description: Use pre-shared key for mutual authentication
required: false
- - name: strict-validation-revocation
- type: bool
+ description: Authentication method
+ required: false
+ - name: comment
+ type: string
+ profiles:
+ - xpath:
+ - comment
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 1023
+ spec: {}
+ description: ""
+ required: false
+ - name: disabled
+ type: bool
+ profiles:
+ - xpath:
+ - disabled
+ validators: []
+ spec: {}
+ description: Disable the IKE gateway
+ required: false
+ - name: ipv6
+ type: bool
+ profiles:
+ - xpath:
+ - ipv6
+ validators: []
+ spec: {}
+ description: use IPv6 for the IKE gateway
+ required: false
+ - name: local-address
+ type: object
+ profiles:
+ - xpath:
+ - local-address
+ validators: []
+ spec:
+ params:
+ - name: interface
+ type: string
profiles:
- - xpath:
- - strict-validation-revocation
+ - xpath:
+ - interface
validators: []
spec: {}
- description: Enable strict validation of peer's extended key use
+ description: local gateway end-point
required: false
- - name: use-management-as-source
- type: bool
+ variants:
+ - name: floating-ip
+ type: string
profiles:
- - xpath:
- - use-management-as-source
+ - xpath:
+ - floating-ip
validators: []
spec: {}
- description: Use management interface IP as source to retrieve http certificates
+ description: Floating IP address in HA Active-Active configuration
required: false
- variants: []
- description: Use RSA or ECDSA digital signature authentication
- required: false
- - name: pre-shared-key
- type: object
- profiles:
- - xpath:
- - pre-shared-key
- validators: []
- spec:
- params:
- - name: key
+ codegen_overrides:
+ terraform:
+ variant_check: ConflictsWith
+ - name: ip
type: string
profiles:
- - xpath:
- - key
+ - xpath:
+ - ip
validators:
- - type: length
- spec:
- max: 255
+ - type: length
+ spec:
+ max: 63
spec: {}
- description: the string used as pre-shared key
+ description: specify exact IP address if interface has multiple addresses
required: false
- variants: []
- description: Use pre-shared key for mutual authentication
- required: false
- description: Authentication method
- required: false
- - name: comment
- type: string
- profiles:
- - xpath:
- - comment
- validators:
- - type: length
- spec:
- min: 0
- max: 1023
- spec: {}
- description: ''
- required: false
- - name: disabled
- type: bool
- profiles:
- - xpath:
- - disabled
- validators: []
- spec: {}
- description: Disable the IKE gateway
- required: false
- - name: ipv6
- type: bool
- profiles:
- - xpath:
- - ipv6
- validators: []
- spec: {}
- description: use IPv6 for the IKE gateway
- required: false
- - name: local-address
- type: object
- profiles:
- - xpath:
- - local-address
- validators: []
- spec:
- params:
- - name: interface
- type: string
- profiles:
- - xpath:
- - interface
- validators: []
- spec: {}
- description: local gateway end-point
- required: false
- variants:
- - name: floating-ip
- type: string
- profiles:
- - xpath:
- - floating-ip
- validators: []
- spec: {}
- description: Floating IP address in HA Active-Active configuration
- required: false
- codegen_overrides:
- terraform:
- variant_check: ConflictsWith
- - name: ip
- type: string
- profiles:
- - xpath:
- - ip
- validators:
- - type: length
- spec:
- max: 63
- spec: {}
- description: specify exact IP address if interface has multiple addresses
- required: false
- description: IKE gateway local IP configuration
- required: false
- - name: local-id
- type: object
- profiles:
- - xpath:
- - local-id
- validators: []
- spec:
- params:
- - name: id
- type: string
- profiles:
- - xpath:
- - id
- validators:
- - type: length
- spec:
- min: 1
- max: 1024
- spec: {}
- description: Local ID string
- required: false
- - name: type
- type: string
- profiles:
- - xpath:
- - type
- validators: []
- spec: {}
- description: ''
- required: false
- variants: []
- description: optionally how peer gateway will identify local gateway instead of
- using IP address
- required: false
- - name: peer-address
- type: object
- profiles:
- - xpath:
- - peer-address
- validators: []
- spec:
- params: []
- variants:
- - name: dynamic
- type: object
- profiles:
- - xpath:
- - dynamic
- validators: []
- spec:
- params: []
- variants: []
- description: peer gateway has dynamic IP address
- required: false
- - name: fqdn
- type: string
- profiles:
- - xpath:
- - fqdn
- validators:
- - type: length
- spec:
- max: 255
- spec: {}
- description: peer gateway FQDN name
- required: false
- - name: ip
- type: string
- profiles:
- - xpath:
- - ip
- validators: []
- spec: {}
- description: peer gateway has static IP address
- required: false
- description: Peer gateway address
- required: false
- - name: peer-id
- type: object
- profiles:
- - xpath:
- - peer-id
- validators: []
- spec:
- params:
- - name: id
- type: string
- profiles:
- - xpath:
- - id
- validators:
- - type: length
- spec:
- min: 1
- max: 1024
- spec: {}
- description: Peer ID string
- required: false
- - name: matching
- type: enum
- profiles:
- - xpath:
- - matching
- validators:
- - type: values
- spec:
- values:
- - exact
- - wildcard
- spec:
- default: exact
- values:
- - value: exact
- - value: wildcard
- description: Enable peer ID wildcard match for certificate authentication
- required: false
- - name: type
- type: string
- profiles:
+ description: IKE gateway local IP configuration
+ required: false
+ - name: local-id
+ type: object
+ profiles:
- xpath:
- - type
- validators: []
- spec: {}
- description: ''
- required: false
- variants: []
- description: optionally how local gateway will identify peer gateway instead of
- using IP address
- required: false
- - name: protocol
- type: object
- profiles:
- - xpath:
- - protocol
- validators: []
- spec:
- params:
- - name: ikev1
- type: object
- profiles:
+ - local-id
+ validators: []
+ spec:
+ params:
+ - name: id
+ type: string
+ profiles:
+ - xpath:
+ - id
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 1024
+ spec: {}
+ description: Local ID string
+ required: false
+ - name: type
+ type: string
+ profiles:
+ - xpath:
+ - type
+ validators: []
+ spec: {}
+ description: ""
+ required: false
+ variants: []
+ description:
+ optionally how peer gateway will identify local gateway instead of
+ using IP address
+ required: false
+ - name: peer-address
+ type: object
+ profiles:
- xpath:
- - ikev1
- validators: []
- spec:
- params:
- - name: dpd
+ - peer-address
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: dynamic
type: object
profiles:
- - xpath:
- - dpd
+ - xpath:
+ - dynamic
validators: []
spec:
- params:
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: Enable Dead-Peer-Detection
- required: false
- - name: interval
- type: int64
- profiles:
- - xpath:
- - interval
- validators:
- - type: length
- spec:
- min: 2
- max: 100
+ params: []
+ variants: []
+ description: peer gateway has dynamic IP address
+ required: false
+ - name: fqdn
+ type: string
+ profiles:
+ - xpath:
+ - fqdn
+ validators:
+ - type: length
spec:
- default: 5
- description: sending interval for probing packets (in seconds)
- required: false
- - name: retry
- type: int64
- profiles:
- - xpath:
- - retry
- validators:
- - type: length
- spec:
- min: 2
- max: 100
+ max: 255
+ spec: {}
+ description: peer gateway FQDN name
+ required: false
+ - name: ip
+ type: string
+ profiles:
+ - xpath:
+ - ip
+ validators: []
+ spec: {}
+ description: peer gateway has static IP address
+ required: false
+ description: Peer gateway address
+ required: false
+ - name: peer-id
+ type: object
+ profiles:
+ - xpath:
+ - peer-id
+ validators: []
+ spec:
+ params:
+ - name: id
+ type: string
+ profiles:
+ - xpath:
+ - id
+ validators:
+ - type: length
spec:
- default: 5
- description: number of retries before disconnection
- required: false
- variants: []
- description: Dead-Peer-Detection settings
+ min: 1
+ max: 1024
+ spec: {}
+ description: Peer ID string
required: false
- - name: exchange-mode
+ - name: matching
type: enum
profiles:
- - xpath:
- - exchange-mode
+ - xpath:
+ - matching
validators:
- - type: values
- spec:
- values:
- - auto
- - main
- - aggressive
+ - type: values
+ spec:
+ values:
+ - exact
+ - wildcard
spec:
- default: auto
+ default: exact
values:
- - value: auto
- - value: main
- - value: aggressive
- description: Exchange mode
+ - value: exact
+ - value: wildcard
+ description: Enable peer ID wildcard match for certificate authentication
required: false
- - name: ike-crypto-profile
+ - name: type
type: string
profiles:
- - xpath:
- - ike-crypto-profile
+ - xpath:
+ - type
validators: []
- spec:
- default: default
- description: IKE SA crypto profile name
+ spec: {}
+ description: ""
required: false
- variants: []
- description: IKEv1 setting
- required: false
- - name: ikev2
- type: object
- profiles:
+ variants: []
+ description:
+ optionally how local gateway will identify peer gateway instead of
+ using IP address
+ required: false
+ - name: protocol
+ type: object
+ profiles:
- xpath:
- - ikev2
- validators: []
- spec:
- params:
- - name: dpd
+ - protocol
+ validators: []
+ spec:
+ params:
+ - name: ikev1
type: object
profiles:
- - xpath:
- - dpd
+ - xpath:
+ - ikev1
validators: []
spec:
params:
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: Enable sending empty information liveness check message
- required: false
- - name: interval
- type: int64
- profiles:
- - xpath:
- - interval
- validators:
- - type: length
+ - name: dpd
+ type: object
+ profiles:
+ - xpath:
+ - dpd
+ validators: []
spec:
- min: 2
- max: 100
- spec:
- default: 5
- description: delay interval before sending probing packets (in seconds)
- required: false
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable Dead-Peer-Detection
+ required: false
+ - name: interval
+ type: int64
+ profiles:
+ - xpath:
+ - interval
+ validators:
+ - type: length
+ spec:
+ min: 2
+ max: 100
+ spec:
+ default: 5
+ description: sending interval for probing packets (in seconds)
+ required: false
+ - name: retry
+ type: int64
+ profiles:
+ - xpath:
+ - retry
+ validators:
+ - type: length
+ spec:
+ min: 2
+ max: 100
+ spec:
+ default: 5
+ description: number of retries before disconnection
+ required: false
+ variants: []
+ description: Dead-Peer-Detection settings
+ required: false
+ - name: exchange-mode
+ type: enum
+ profiles:
+ - xpath:
+ - exchange-mode
+ validators:
+ - type: values
+ spec:
+ values:
+ - auto
+ - main
+ - aggressive
+ spec:
+ default: auto
+ values:
+ - value: auto
+ - value: main
+ - value: aggressive
+ description: Exchange mode
+ required: false
+ - name: ike-crypto-profile
+ type: string
+ profiles:
+ - xpath:
+ - ike-crypto-profile
+ validators: []
+ spec:
+ default: default
+ description: IKE SA crypto profile name
+ required: false
variants: []
- description: IKEv2 liveness check setting
+ description: IKEv1 setting
required: false
- - name: ike-crypto-profile
- type: string
+ - name: ikev2
+ type: object
profiles:
- - xpath:
- - ike-crypto-profile
+ - xpath:
+ - ikev2
validators: []
spec:
- default: default
- description: IKE SA crypto profile name
+ params:
+ - name: dpd
+ type: object
+ profiles:
+ - xpath:
+ - dpd
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable sending empty information liveness check message
+ required: false
+ - name: interval
+ type: int64
+ profiles:
+ - xpath:
+ - interval
+ validators:
+ - type: length
+ spec:
+ min: 2
+ max: 100
+ spec:
+ default: 5
+ description: delay interval before sending probing packets (in seconds)
+ required: false
+ variants: []
+ description: IKEv2 liveness check setting
+ required: false
+ - name: ike-crypto-profile
+ type: string
+ profiles:
+ - xpath:
+ - ike-crypto-profile
+ validators: []
+ spec:
+ default: default
+ description: IKE SA crypto profile name
+ required: false
+ - name: require-cookie
+ type: bool
+ profiles:
+ - xpath:
+ - require-cookie
+ validators: []
+ spec: {}
+ description: Require cookie
+ required: false
+ variants: []
+ description: IKEv2 setting
required: false
- - name: require-cookie
- type: bool
+ - name: version
+ type: enum
profiles:
- - xpath:
- - require-cookie
- validators: []
- spec: {}
- description: Require cookie
+ - xpath:
+ - version
+ validators:
+ - type: values
+ spec:
+ values:
+ - ikev1
+ - ikev2
+ - ikev2-preferred
+ spec:
+ default: ikev1
+ values:
+ - value: ikev1
+ - value: ikev2
+ - value: ikev2-preferred
+ description: IKE protocol version
required: false
- variants: []
- description: IKEv2 setting
- required: false
- - name: version
- type: enum
- profiles:
- - xpath:
- - version
- validators:
- - type: values
- spec:
- values:
- - ikev1
- - ikev2
- - ikev2-preferred
- spec:
- default: ikev1
- values:
- - value: ikev1
- - value: ikev2
- - value: ikev2-preferred
- description: IKE protocol version
- required: false
- variants: []
- description: IKE Protocol settings
- required: false
- - name: protocol-common
- type: object
- profiles:
- - xpath:
- - protocol-common
- validators: []
- spec:
- params:
- - name: fragmentation
- type: object
- profiles:
+ variants: []
+ description: IKE Protocol settings
+ required: false
+ - name: protocol-common
+ type: object
+ profiles:
- xpath:
- - fragmentation
- validators: []
- spec:
- params:
- - name: enable
- type: bool
+ - protocol-common
+ validators: []
+ spec:
+ params:
+ - name: fragmentation
+ type: object
profiles:
- - xpath:
- - enable
+ - xpath:
+ - fragmentation
validators: []
- spec: {}
- description: Enable IKE fragmentation
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable IKE fragmentation
+ required: false
+ variants: []
+ description: IKE fragmentation settings
required: false
- variants: []
- description: IKE fragmentation settings
- required: false
- - name: nat-traversal
- type: object
- profiles:
- - xpath:
- - nat-traversal
- validators: []
- spec:
- params:
- - name: enable
- type: bool
+ - name: nat-traversal
+ type: object
profiles:
- - xpath:
- - enable
+ - xpath:
+ - nat-traversal
validators: []
- spec: {}
- description: Enable NAT-Traversal
- required: false
- - name: keep-alive-interval
- type: int64
- profiles:
- - xpath:
- - keep-alive-interval
- validators:
- - type: length
- spec:
- min: 10
- max: 3600
spec:
- default: 20
- description: sending interval for NAT keep-alive packets (in seconds)
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable NAT-Traversal
+ required: false
+ - name: keep-alive-interval
+ type: int64
+ profiles:
+ - xpath:
+ - keep-alive-interval
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 3600
+ spec:
+ default: 20
+ description: sending interval for NAT keep-alive packets (in seconds)
+ required: false
+ - name: udp-checksum-enable
+ type: bool
+ profiles:
+ - xpath:
+ - udp-checksum-enable
+ validators: []
+ spec: {}
+ description: Enable UDP checksum
+ required: false
+ variants: []
+ description: NAT-Traversal settings
required: false
- - name: udp-checksum-enable
+ - name: passive-mode
type: bool
profiles:
- - xpath:
- - udp-checksum-enable
+ - xpath:
+ - passive-mode
validators: []
spec: {}
- description: Enable UDP checksum
+ description: Enable passive mode (responder only)
required: false
- variants: []
- description: NAT-Traversal settings
- required: false
- - name: passive-mode
- type: bool
- profiles:
- - xpath:
- - passive-mode
- validators: []
- spec: {}
- description: Enable passive mode (responder only)
- required: false
- variants: []
- description: IKE Protocol settings common to IKEv1 and IKEv2 (IKEv2 to be supported
- in the future)
- required: false
+ variants: []
+ description:
+ IKE Protocol settings common to IKEv1 and IKEv2 (IKEv2 to be supported
+ in the future)
+ required: false
variants: []
diff --git a/specs/network/interface/aggregate.yaml b/specs/network/interface/aggregate.yaml
index 3be99f58..bde440a6 100644
--- a/specs/network/interface/aggregate.yaml
+++ b/specs/network/interface/aggregate.yaml
@@ -16,10 +16,12 @@ go_sdk_config:
- network
- interface
- aggregate
-xpath_suffix:
-- network
-- interface
-- aggregate-ethernet
+panos_xpath:
+ path:
+ - network
+ - interface
+ - aggregate-ethernet
+ vars: []
locations:
- name: shared
xpath:
@@ -155,6 +157,7 @@ spec:
variants: []
description: Interface to mirror decrypted packet
required: false
+ variant_group_id: 0
- name: ha
type: object
profiles:
@@ -259,6 +262,7 @@ spec:
variants: []
description: Interface for high-availability functions
required: false
+ variant_group_id: 0
- name: layer2
type: object
profiles:
@@ -444,6 +448,7 @@ spec:
variants: []
description: Layer2 interface
required: false
+ variant_group_id: 0
- name: layer3
type: object
profiles:
@@ -941,135 +946,76 @@ spec:
variants: []
description: ''
required: false
- - name: enabled
- type: bool
- profiles:
- - xpath:
- - enabled
- validators: []
- spec: {}
- description: Enable IPv6 on the interface
- required: false
- - name: interface-id
- type: string
- profiles:
- - xpath:
- - interface-id
- validators: []
- spec:
- default: EUI-64
- description: ''
- required: false
- - name: neighbor-discovery
+ - name: dhcp-client
type: object
profiles:
- xpath:
- - neighbor-discovery
+ - dhcp-client
+ min_version: 11.0.2
+ max_version: 11.0.3
validators: []
spec:
params:
- - name: dad-attempts
- type: int64
- profiles:
- - xpath:
- - dad-attempts
- validators:
- - type: length
- spec:
- min: 0
- max: 10
- spec:
- default: 1
- description: number of consecutive neighbor solicitation messages
- sent for duplicate address detection
- required: false
- - name: enable-dad
- type: bool
- profiles:
- - xpath:
- - enable-dad
- validators: []
- spec: {}
- description: enable duplicate address detection
- required: false
- - name: enable-ndp-monitor
+ - name: accept-ra-route
type: bool
profiles:
- xpath:
- - enable-ndp-monitor
+ - accept-ra-route
validators: []
spec: {}
- description: enable ndp monitoring
- required: false
- - name: neighbor
- type: list
- profiles:
- - xpath:
- - neighbor
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: hw-address
- type: string
- profiles:
- - xpath:
- - hw-address
- validators: []
- spec: {}
- description: MAC address (format xx:xx:xx:xx:xx:xx)
- required: false
- variants: []
- description: ''
+ description: Accept Router Advertised Default Route
required: false
- - name: ns-interval
+ - name: default-route-metric
type: int64
profiles:
- xpath:
- - ns-interval
+ - default-route-metric
validators:
- type: length
spec:
min: 1
- max: 3600
+ max: 65535
spec:
- default: 1
- description: interval (in seconds) between consecutive neighbor solicitation
- messages
+ default: 10
+ description: Metric of the default route created
required: false
- - name: reachable-time
- type: int64
+ - name: enable
+ type: bool
profiles:
- xpath:
- - reachable-time
- validators:
- - type: length
- spec:
- min: 10
- max: 36000
- spec:
- default: 30
- description: time (in seconds) that the Reachable status for a neighbor
- can be maintained
+ - enable
+ validators: []
+ spec: {}
+ description: Enable DHCPv6 Client
required: false
- - name: router-advertisement
+ - name: neighbor-discovery
type: object
profiles:
- xpath:
- - router-advertisement
+ - neighbor-discovery
validators: []
spec:
params:
- - name: dns-support
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 10
+ spec:
+ default: 1
+ description: number of consecutive neighbor solicitation messages
+ sent for duplicate address detection
+ required: false
+ - name: dns-server
type: object
profiles:
- xpath:
- - dns-support
+ - dns-server
validators: []
spec:
params:
@@ -1082,729 +1028,429 @@ spec:
spec: {}
description: ''
required: false
- - name: server
- type: list
+ - name: source
+ type: object
profiles:
- xpath:
- - server
- - entry
- type: entry
+ - source
validators: []
spec:
- type: object
- items:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
spec:
params:
- - name: lifetime
- type: int64
+ - name: server
+ type: list
profiles:
- xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
+ - server
+ - entry
+ type: entry
+ validators: []
spec:
- default: 1200
- description: (4-3600) lifetime in seconds
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) Lifetime in Seconds
+ required: false
+ variants: []
+ description: ''
required: false
variants: []
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually
+ configure
+ required: false
+ variants: []
+ description: DNS Recursive Name Server
+ required: false
+ - name: dns-suffix
+ type: object
+ profiles:
+ - xpath:
+ - dns-suffix
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
description: ''
required: false
- - name: suffix
- type: list
+ - name: source
+ type: object
profiles:
- xpath:
- - suffix
- - entry
- type: entry
+ - source
validators: []
spec:
- type: object
- items:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
spec:
params:
- - name: lifetime
- type: int64
+ - name: suffix
+ type: list
profiles:
- xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
+ - suffix
+ - entry
+ type: entry
+ validators: []
spec:
- default: 1200
- description: (4-3600) lifetime in seconds
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
required: false
variants: []
- description: ''
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually
+ configure
required: false
variants: []
- description: DNS configuration support
+ description: Domain Search List
required: false
- - name: enable
+ - name: enable-dad
type: bool
profiles:
- xpath:
- - enable
+ - enable-dad
validators: []
spec: {}
- description: ''
+ description: Enable Duplicate Address Detection
required: false
- - name: enable-consistency-check
+ - name: enable-ndp-monitor
type: bool
profiles:
- xpath:
- - enable-consistency-check
+ - enable-ndp-monitor
validators: []
spec: {}
- description: check consistency of RA messages from other routers.
- required: false
- - name: hop-limit
- type: string
- profiles:
- - xpath:
- - hop-limit
- validators: []
- spec:
- default: '64'
- description: Current Hop Limit advertised in Router Advertisement
- messages
- required: false
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 0
- max: 9000
- spec:
- default: 1800
- description: Router Lifetime (in seconds) advertised in Router
- Advertisement messages
- required: false
- - name: link-mtu
- type: string
- profiles:
- - xpath:
- - link-mtu
- validators: []
- spec:
- default: unspecified
- description: value of MTU option in Router Advertisement messages,
- upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
+ description: Enable NDP Monitoring
required: false
- - name: managed-flag
- type: bool
+ - name: neighbor
+ type: list
profiles:
- xpath:
- - managed-flag
+ - neighbor
+ - entry
+ type: entry
validators: []
- spec: {}
- description: Set the Managed Configuration Flag (M-bit) in Router
- Advertisement messages
- required: false
- - name: max-interval
- type: int64
- profiles:
- - xpath:
- - max-interval
- validators:
- - type: length
- spec:
- min: 4
- max: 1800
spec:
- default: 600
- description: Maximum interval (seconds) between consecutive unsolicited
- Router Advertisement messages
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
required: false
- - name: min-interval
+ - name: ns-interval
type: int64
profiles:
- xpath:
- - min-interval
+ - ns-interval
validators:
- type: length
spec:
- min: 3
- max: 1350
+ min: 1
+ max: 3600
spec:
- default: 200
- description: Minimum interval (seconds) between consecutive unsolicited
- Router Advertisement messages
- required: false
- - name: other-flag
- type: bool
- profiles:
- - xpath:
- - other-flag
- validators: []
- spec: {}
- description: Set the Other Stateful Configuration Flag (O-bit)
- in Router Advertisement messages
+ default: 1
+ description: interval (in seconds) between consecutive neighbor
+ solicitation messages
required: false
- name: reachable-time
- type: string
+ type: int64
profiles:
- xpath:
- reachable-time
- validators: []
- spec:
- default: unspecified
- description: Reachable Time (in milliseconds) advertised in Router
- Advertisement messages
- required: false
- - name: retransmission-timer
- type: string
- profiles:
- - xpath:
- - retransmission-timer
- validators: []
- spec:
- default: unspecified
- description: Retransmission Timer (in milliseconds) advertised
- in Router Advertisement messages
- required: false
- - name: router-preference
- type: enum
- profiles:
- - xpath:
- - router-preference
validators:
- - type: values
+ - type: length
spec:
- values:
- - High
- - Medium
- - Low
+ min: 10
+ max: 36000
spec:
- default: Medium
- values:
- - value: High
- - value: Medium
- - value: Low
- description: ''
+ default: 30
+ description: time (in seconds) that the Reachable status for a
+ neighbor can be maintained
required: false
variants: []
- description: Router advertisement configuration
- required: false
- variants: []
- description: Neighbor Discovery configuration
- required: false
- - name: dhcp-client
- type: object
- profiles:
- - xpath:
- - dhcp-client
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec:
- params:
- - name: accept-ra-route
- type: bool
- profiles:
- - xpath:
- - accept-ra-route
- validators: []
- spec: {}
- description: Accept Router Advertised Default Route
+ description: Neighbor Discovery configuration
required: false
- - name: default-route-metric
- type: int64
+ - name: preference
+ type: enum
profiles:
- xpath:
- - default-route-metric
+ - preference
validators:
- - type: length
+ - type: values
spec:
- min: 1
- max: 65535
+ values:
+ - low
+ - medium
+ - high
spec:
- default: 10
- description: Metric of the default route created
- required: false
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: Enable DHCPv6 Client
+ default: high
+ values:
+ - value: low
+ - value: medium
+ - value: high
+ description: Select Low/Medium/High
required: false
- - name: neighbor-discovery
+ - name: prefix-delegation
type: object
profiles:
- xpath:
- - neighbor-discovery
+ - prefix-delegation
validators: []
spec:
params:
- - name: dad-attempts
- type: int64
- profiles:
- - xpath:
- - dad-attempts
- validators:
- - type: length
- spec:
- min: 1
- max: 10
- spec:
- default: 1
- description: number of consecutive neighbor solicitation messages
- sent for duplicate address detection
- required: false
- - name: dns-server
+ - name: enable
type: object
profiles:
- xpath:
- - dns-server
+ - enable
validators: []
spec:
- params:
- - name: enable
- type: bool
+ params: []
+ variants:
+ - name: 'no'
+ type: object
profiles:
- xpath:
- - enable
+ - 'no'
validators: []
- spec: {}
- description: ''
+ spec:
+ params: []
+ variants: []
+ description: Disable Prefix Delegation
required: false
- - name: source
+ - name: 'yes'
type: object
profiles:
- xpath:
- - source
+ - 'yes'
validators: []
spec:
- params: []
- variants:
- - name: dhcpv6
- type: object
+ params:
+ - name: pfx-pool-name
+ type: string
profiles:
- xpath:
- - dhcpv6
- validators: []
+ - pfx-pool-name
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Configure unique Prefix Pool Name
+ required: false
+ - name: prefix-len
+ type: int64
+ profiles:
+ - xpath:
+ - prefix-len
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 128
spec:
- params: []
- variants: []
- description: Source from DHCPv6 Server
+ default: 48
+ description: Hint DHCP Prefix Length (bits)
required: false
- - name: manual
- type: object
+ - name: prefix-len-hint
+ type: bool
profiles:
- xpath:
- - manual
+ - prefix-len-hint
validators: []
- spec:
- params:
- - name: server
- type: list
- profiles:
- - xpath:
- - server
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
- spec:
- default: 1200
- description: (4-3600) Lifetime in Seconds
- required: false
- variants: []
- description: ''
- required: false
- variants: []
- description: Configure manually
+ spec: {}
+ description: Send prefix length hint to server
required: false
- description: Either source from DHCPv6 Server or manually
- configure
+ variants: []
+ description: Enable Prefix Delegation
required: false
- variants: []
- description: DNS Recursive Name Server
+ description: Enable/Disable Prefix Delegation
required: false
- - name: dns-suffix
+ variants: []
+ description: Configure Prefix Delegation Options
+ required: false
+ - name: v6-options
+ type: object
+ profiles:
+ - xpath:
+ - v6-options
+ validators: []
+ spec:
+ params:
+ - name: duid-type
+ type: enum
+ profiles:
+ - xpath:
+ - duid-type
+ validators:
+ - type: values
+ spec:
+ values:
+ - duid-type-llt
+ - duid-type-ll
+ spec:
+ default: duid-type-llt
+ values:
+ - value: duid-type-llt
+ - value: duid-type-ll
+ description: Select DUID-LLT/DUID-LL
+ required: false
+ - name: enable
type: object
profiles:
- xpath:
- - dns-suffix
+ - enable
validators: []
spec:
- params:
- - name: enable
- type: bool
+ params: []
+ variants:
+ - name: 'no'
+ type: object
profiles:
- xpath:
- - enable
+ - 'no'
validators: []
- spec: {}
- description: ''
+ spec:
+ params: []
+ variants: []
+ description: Disable IPv6 Address
required: false
- - name: source
+ - name: 'yes'
type: object
profiles:
- xpath:
- - source
+ - 'yes'
validators: []
spec:
- params: []
- variants:
- - name: dhcpv6
- type: object
+ params:
+ - name: non-temp-addr
+ type: bool
profiles:
- xpath:
- - dhcpv6
+ - non-temp-addr
validators: []
- spec:
- params: []
- variants: []
- description: Source from DHCPv6 Server
+ spec: {}
+ description: Request Non-Temporary Address Type
required: false
- - name: manual
- type: object
+ - name: temp-addr
+ type: bool
profiles:
- xpath:
- - manual
+ - temp-addr
validators: []
- spec:
- params:
- - name: suffix
- type: list
- profiles:
- - xpath:
- - suffix
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
- spec:
- default: 1200
- description: (4-3600) lifetime in seconds
- required: false
- variants: []
- description: ''
- required: false
- variants: []
- description: Configure manually
+ spec: {}
+ description: Request Temporary Address Type
required: false
- description: Either source from DHCPv6 Server or manually
- configure
+ variants: []
+ description: Enable IPv6 Address
required: false
- variants: []
- description: Domain Search List
+ description: Enable/Disable IPv6 Address
required: false
- - name: enable-dad
+ - name: rapid-commit
type: bool
profiles:
- xpath:
- - enable-dad
+ - rapid-commit
validators: []
spec: {}
- description: Enable Duplicate Address Detection
+ description: Enable Rapid Commit
required: false
- - name: enable-ndp-monitor
+ - name: support-srvr-reconfig
type: bool
profiles:
- xpath:
- - enable-ndp-monitor
+ - support-srvr-reconfig
validators: []
spec: {}
- description: Enable NDP Monitoring
- required: false
- - name: neighbor
- type: list
- profiles:
- - xpath:
- - neighbor
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: hw-address
- type: string
- profiles:
- - xpath:
- - hw-address
- validators: []
- spec: {}
- description: MAC address (format xx:xx:xx:xx:xx:xx)
- required: false
- variants: []
- description: ''
- required: false
- - name: ns-interval
- type: int64
- profiles:
- - xpath:
- - ns-interval
- validators:
- - type: length
- spec:
- min: 1
- max: 3600
- spec:
- default: 1
- description: interval (in seconds) between consecutive neighbor
- solicitation messages
- required: false
- - name: reachable-time
- type: int64
- profiles:
- - xpath:
- - reachable-time
- validators:
- - type: length
- spec:
- min: 10
- max: 36000
- spec:
- default: 30
- description: time (in seconds) that the Reachable status for a
- neighbor can be maintained
- required: false
- variants: []
- description: Neighbor Discovery configuration
- required: false
- - name: preference
- type: enum
- profiles:
- - xpath:
- - preference
- validators:
- - type: values
- spec:
- values:
- - low
- - medium
- - high
- spec:
- default: high
- values:
- - value: low
- - value: medium
- - value: high
- description: Select Low/Medium/High
- required: false
- - name: prefix-delegation
- type: object
- profiles:
- - xpath:
- - prefix-delegation
- validators: []
- spec:
- params:
- - name: enable
- type: object
- profiles:
- - xpath:
- - enable
- validators: []
- spec:
- params: []
- variants:
- - name: 'no'
- type: object
- profiles:
- - xpath:
- - 'no'
- validators: []
- spec:
- params: []
- variants: []
- description: Disable Prefix Delegation
- required: false
- - name: 'yes'
- type: object
- profiles:
- - xpath:
- - 'yes'
- validators: []
- spec:
- params:
- - name: pfx-pool-name
- type: string
- profiles:
- - xpath:
- - pfx-pool-name
- validators:
- - type: length
- spec:
- max: 63
- spec: {}
- description: Configure unique Prefix Pool Name
- required: false
- - name: prefix-len
- type: int64
- profiles:
- - xpath:
- - prefix-len
- validators:
- - type: length
- spec:
- min: 0
- max: 128
- spec:
- default: 48
- description: Hint DHCP Prefix Length (bits)
- required: false
- - name: prefix-len-hint
- type: bool
- profiles:
- - xpath:
- - prefix-len-hint
- validators: []
- spec: {}
- description: Send prefix length hint to server
- required: false
- variants: []
- description: Enable Prefix Delegation
- required: false
- description: Enable/Disable Prefix Delegation
- required: false
- variants: []
- description: Configure Prefix Delegation Options
- required: false
- - name: v6-options
- type: object
- profiles:
- - xpath:
- - v6-options
- validators: []
- spec:
- params:
- - name: duid-type
- type: enum
- profiles:
- - xpath:
- - duid-type
- validators:
- - type: values
- spec:
- values:
- - duid-type-llt
- - duid-type-ll
- spec:
- default: duid-type-llt
- values:
- - value: duid-type-llt
- - value: duid-type-ll
- description: Select DUID-LLT/DUID-LL
- required: false
- - name: enable
- type: object
- profiles:
- - xpath:
- - enable
- validators: []
- spec:
- params: []
- variants:
- - name: 'no'
- type: object
- profiles:
- - xpath:
- - 'no'
- validators: []
- spec:
- params: []
- variants: []
- description: Disable IPv6 Address
- required: false
- - name: 'yes'
- type: object
- profiles:
- - xpath:
- - 'yes'
- validators: []
- spec:
- params:
- - name: non-temp-addr
- type: bool
- profiles:
- - xpath:
- - non-temp-addr
- validators: []
- spec: {}
- description: Request Non-Temporary Address Type
- required: false
- - name: temp-addr
- type: bool
- profiles:
- - xpath:
- - temp-addr
- validators: []
- spec: {}
- description: Request Temporary Address Type
- required: false
- variants: []
- description: Enable IPv6 Address
- required: false
- description: Enable/Disable IPv6 Address
- required: false
- - name: rapid-commit
- type: bool
- profiles:
- - xpath:
- - rapid-commit
- validators: []
- spec: {}
- description: Enable Rapid Commit
- required: false
- - name: support-srvr-reconfig
- type: bool
- profiles:
- - xpath:
- - support-srvr-reconfig
- validators: []
- spec: {}
- description: Enable DHCPv6 Server Re-Configuration Support
+ description: Enable DHCPv6 Server Re-Configuration Support
required: false
variants: []
description: Configure DHCPv6 Options
@@ -1812,6 +1458,15 @@ spec:
variants: []
description: Configure DHCPv6 Client
required: false
+ - name: enabled
+ type: bool
+ profiles:
+ - xpath:
+ - enabled
+ validators: []
+ spec: {}
+ description: Enable IPv6 on the interface
+ required: false
- name: inherited
type: object
profiles:
@@ -2552,6 +2207,356 @@ spec:
variants: []
description: Configure to inherit properties from another interface
required: false
+ - name: interface-id
+ type: string
+ profiles:
+ - xpath:
+ - interface-id
+ validators: []
+ spec:
+ default: EUI-64
+ description: ''
+ required: false
+ - name: neighbor-discovery
+ type: object
+ profiles:
+ - xpath:
+ - neighbor-discovery
+ validators: []
+ spec:
+ params:
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 10
+ spec:
+ default: 1
+ description: number of consecutive neighbor solicitation messages
+ sent for duplicate address detection
+ required: false
+ - name: enable-dad
+ type: bool
+ profiles:
+ - xpath:
+ - enable-dad
+ validators: []
+ spec: {}
+ description: enable duplicate address detection
+ required: false
+ - name: enable-ndp-monitor
+ type: bool
+ profiles:
+ - xpath:
+ - enable-ndp-monitor
+ validators: []
+ spec: {}
+ description: enable ndp monitoring
+ required: false
+ - name: neighbor
+ type: list
+ profiles:
+ - xpath:
+ - neighbor
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: ns-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ns-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 3600
+ spec:
+ default: 1
+ description: interval (in seconds) between consecutive neighbor solicitation
+ messages
+ required: false
+ - name: reachable-time
+ type: int64
+ profiles:
+ - xpath:
+ - reachable-time
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 36000
+ spec:
+ default: 30
+ description: time (in seconds) that the Reachable status for a neighbor
+ can be maintained
+ required: false
+ - name: router-advertisement
+ type: object
+ profiles:
+ - xpath:
+ - router-advertisement
+ validators: []
+ spec:
+ params:
+ - name: dns-support
+ type: object
+ profiles:
+ - xpath:
+ - dns-support
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: server
+ type: list
+ profiles:
+ - xpath:
+ - server
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: suffix
+ type: list
+ profiles:
+ - xpath:
+ - suffix
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: DNS configuration support
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: enable-consistency-check
+ type: bool
+ profiles:
+ - xpath:
+ - enable-consistency-check
+ validators: []
+ spec: {}
+ description: check consistency of RA messages from other routers.
+ required: false
+ - name: hop-limit
+ type: string
+ profiles:
+ - xpath:
+ - hop-limit
+ validators: []
+ spec:
+ default: '64'
+ description: Current Hop Limit advertised in Router Advertisement
+ messages
+ required: false
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 9000
+ spec:
+ default: 1800
+ description: Router Lifetime (in seconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: link-mtu
+ type: string
+ profiles:
+ - xpath:
+ - link-mtu
+ validators: []
+ spec:
+ default: unspecified
+ description: value of MTU option in Router Advertisement messages,
+ upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
+ required: false
+ - name: managed-flag
+ type: bool
+ profiles:
+ - xpath:
+ - managed-flag
+ validators: []
+ spec: {}
+ description: Set the Managed Configuration Flag (M-bit) in Router
+ Advertisement messages
+ required: false
+ - name: max-interval
+ type: int64
+ profiles:
+ - xpath:
+ - max-interval
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 1800
+ spec:
+ default: 600
+ description: Maximum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: min-interval
+ type: int64
+ profiles:
+ - xpath:
+ - min-interval
+ validators:
+ - type: length
+ spec:
+ min: 3
+ max: 1350
+ spec:
+ default: 200
+ description: Minimum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: other-flag
+ type: bool
+ profiles:
+ - xpath:
+ - other-flag
+ validators: []
+ spec: {}
+ description: Set the Other Stateful Configuration Flag (O-bit)
+ in Router Advertisement messages
+ required: false
+ - name: reachable-time
+ type: string
+ profiles:
+ - xpath:
+ - reachable-time
+ validators: []
+ spec:
+ default: unspecified
+ description: Reachable Time (in milliseconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: retransmission-timer
+ type: string
+ profiles:
+ - xpath:
+ - retransmission-timer
+ validators: []
+ spec:
+ default: unspecified
+ description: Retransmission Timer (in milliseconds) advertised
+ in Router Advertisement messages
+ required: false
+ - name: router-preference
+ type: enum
+ profiles:
+ - xpath:
+ - router-preference
+ validators:
+ - type: values
+ spec:
+ values:
+ - High
+ - Medium
+ - Low
+ spec:
+ default: Medium
+ values:
+ - value: High
+ - value: Medium
+ - value: Low
+ description: ''
+ required: false
+ variants: []
+ description: Router advertisement configuration
+ required: false
+ variants: []
+ description: Neighbor Discovery configuration
+ required: false
variants: []
description: Interface IPv6 configuration
required: false
@@ -2847,6 +2852,7 @@ spec:
variants: []
description: DDNS derives upstream NAT IP
required: false
+ variant_group_id: 0
- name: static-ip
type: object
profiles:
@@ -2868,6 +2874,7 @@ spec:
spec: {}
description: Upstream NAT address FQDN name configuration
required: false
+ variant_group_id: 0
- name: ip-address
type: string
profiles:
@@ -2877,8 +2884,10 @@ spec:
spec: {}
description: Upstream NAT IP address
required: false
+ variant_group_id: 0
description: Upstream NAT IP address
required: false
+ variant_group_id: 0
description: Upstream NAT IP config
required: false
variants: []
@@ -2896,6 +2905,7 @@ spec:
variants: []
description: Layer3 interface
required: false
+ variant_group_id: 0
- name: virtual-wire
type: object
profiles:
@@ -2968,3 +2978,4 @@ spec:
variants: []
description: Virtual-wire interface
required: false
+ variant_group_id: 0
diff --git a/specs/network/interface/ethernet.yaml b/specs/network/interface/ethernet.yaml
index b78bd216..b47b79e7 100644
--- a/specs/network/interface/ethernet.yaml
+++ b/specs/network/interface/ethernet.yaml
@@ -16,10 +16,12 @@ go_sdk_config:
- network
- interface
- ethernet
-xpath_suffix:
-- network
-- interface
-- ethernet
+panos_xpath:
+ path:
+ - network
+ - interface
+ - ethernet
+ vars: []
locations:
- name: shared
xpath:
@@ -388,6 +390,7 @@ spec:
spec: {}
description: Aggregate interface group
required: false
+ variant_group_id: 0
- name: decrypt-mirror
type: object
profiles:
@@ -399,6 +402,7 @@ spec:
variants: []
description: Interface to mirror decrypted packet
required: false
+ variant_group_id: 0
- name: ha
type: object
profiles:
@@ -410,6 +414,7 @@ spec:
variants: []
description: HA mode interface
required: false
+ variant_group_id: 0
- name: layer2
type: object
profiles:
@@ -482,6 +487,7 @@ spec:
variants: []
description: Layer2 interface
required: false
+ variant_group_id: 0
- name: layer3
type: object
profiles:
@@ -607,6 +613,17 @@ spec:
variants: []
description: Bonjour configuration
required: false
+ - name: cluster-interconnect
+ type: bool
+ profiles:
+ - xpath:
+ - cluster-interconnect
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec: {}
+ description: ''
+ required: false
- name: ddns-config
type: object
profiles:
@@ -985,135 +1002,76 @@ spec:
codegen_overrides:
terraform:
name: addresses
- - name: enabled
- type: bool
- profiles:
- - xpath:
- - enabled
- validators: []
- spec: {}
- description: Enable IPv6 on the interface
- required: false
- - name: interface-id
- type: string
- profiles:
- - xpath:
- - interface-id
- validators: []
- spec:
- default: EUI-64
- description: ''
- required: false
- - name: neighbor-discovery
+ - name: dhcp-client
type: object
profiles:
- xpath:
- - neighbor-discovery
+ - dhcp-client
+ min_version: 11.0.2
+ max_version: 11.0.3
validators: []
spec:
params:
- - name: dad-attempts
- type: int64
- profiles:
- - xpath:
- - dad-attempts
- validators:
- - type: length
- spec:
- min: 0
- max: 10
- spec:
- default: 1
- description: Number of consecutive neighbor solicitation messages
- sent for duplicate address detection
- required: false
- - name: enable-dad
- type: bool
- profiles:
- - xpath:
- - enable-dad
- validators: []
- spec: {}
- description: Enable Duplicate ADdress Detection (DAD)
- required: false
- - name: enable-ndp-monitor
+ - name: accept-ra-route
type: bool
profiles:
- xpath:
- - enable-ndp-monitor
+ - accept-ra-route
validators: []
spec: {}
- description: Enable NDP Monitoring
- required: false
- - name: neighbor
- type: list
- profiles:
- - xpath:
- - neighbor
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: hw-address
- type: string
- profiles:
- - xpath:
- - hw-address
- validators: []
- spec: {}
- description: MAC address (format xx:xx:xx:xx:xx:xx)
- required: false
- variants: []
- description: Static entries in neighbor cache
+ description: Accept Router Advertised Default Route
required: false
- - name: ns-interval
+ - name: default-route-metric
type: int64
profiles:
- xpath:
- - ns-interval
+ - default-route-metric
validators:
- type: length
spec:
min: 1
- max: 3600
+ max: 65535
spec:
- default: 1
- description: Interval (in seconds) between consecutive neighbor solicitation
- messages
+ default: 10
+ description: Metric of the default route created
required: false
- - name: reachable-time
- type: int64
+ - name: enable
+ type: bool
profiles:
- xpath:
- - reachable-time
- validators:
- - type: length
- spec:
- min: 10
- max: 36000
- spec:
- default: 30
- description: Time (in seconds) that the Reachable status for a neighbor
- can be maintained
+ - enable
+ validators: []
+ spec: {}
+ description: Enable DHCPv6 Client
required: false
- - name: router-advertisement
+ - name: neighbor-discovery
type: object
profiles:
- xpath:
- - router-advertisement
+ - neighbor-discovery
validators: []
spec:
params:
- - name: dns-support
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 10
+ spec:
+ default: 1
+ description: Number of consecutive neighbor solicitation messages
+ sent for duplicate address detection
+ required: false
+ - name: dns-server
type: object
profiles:
- xpath:
- - dns-support
+ - dns-server
validators: []
spec:
params:
@@ -1126,296 +1084,79 @@ spec:
spec: {}
description: ''
required: false
- - name: server
- type: list
+ - name: source
+ type: object
profiles:
- xpath:
- - server
- - entry
- type: entry
+ - source
validators: []
spec:
- type: object
- items:
+ params: []
+ variants:
+ - name: dhcpv6
type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
spec:
- params:
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
- spec:
- default: 1200
- description: Router Lifetime (in seconds) advertised
- in Router Advertisement messages
- required: false
+ params: []
variants: []
- description: ''
- required: false
- - name: suffix
- type: list
- profiles:
- - xpath:
- - suffix
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
spec:
params:
- - name: lifetime
- type: int64
+ - name: server
+ type: list
profiles:
- xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
+ - server
+ - entry
+ type: entry
+ validators: []
spec:
- default: 1200
- description: Router Lifetime (in seconds) advertised
- in Router Advertisement messages
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) Lifetime in Seconds
+ required: false
+ variants: []
+ description: ''
required: false
variants: []
- description: ''
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually
+ configure
required: false
variants: []
- description: DNS configuration support
+ description: DNS Recursive Name Server
required: false
- - name: enable
- type: bool
+ - name: dns-suffix
+ type: object
profiles:
- xpath:
- - enable
- validators: []
- spec: {}
- description: ''
- required: false
- - name: enable-consistency-check
- type: bool
- profiles:
- - xpath:
- - enable-consistency-check
- validators: []
- spec: {}
- description: check consistency of RA messages from other routers.
- required: false
- - name: hop-limit
- type: string
- profiles:
- - xpath:
- - hop-limit
- validators: []
- spec:
- default: '64'
- description: Current Hop Limit advertised in Router Advertisement
- messages
- required: false
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 0
- max: 9000
- spec:
- default: 1800
- description: Router Lifetime (in seconds) advertised in Router
- Advertisement messages
- required: false
- - name: link-mtu
- type: string
- profiles:
- - xpath:
- - link-mtu
- validators: []
- spec:
- default: unspecified
- description: value of MTU option in Router Advertisement messages,
- upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
- required: false
- - name: managed-flag
- type: bool
- profiles:
- - xpath:
- - managed-flag
- validators: []
- spec: {}
- description: Set the Managed Configuration Flag (M-bit) in Router
- Advertisement messages
- required: false
- - name: max-interval
- type: int64
- profiles:
- - xpath:
- - max-interval
- validators:
- - type: length
- spec:
- min: 4
- max: 1800
- spec:
- default: 600
- description: Maximum interval (seconds) between consecutive unsolicited
- Router Advertisement messages
- required: false
- - name: min-interval
- type: int64
- profiles:
- - xpath:
- - min-interval
- validators:
- - type: length
- spec:
- min: 3
- max: 1350
- spec:
- default: 200
- description: Minimum interval (seconds) between consecutive unsolicited
- Router Advertisement messages
- required: false
- - name: other-flag
- type: bool
- profiles:
- - xpath:
- - other-flag
- validators: []
- spec: {}
- description: Set the Other Stateful Configuration Flag (O-bit)
- in Router Advertisement messages
- required: false
- - name: reachable-time
- type: string
- profiles:
- - xpath:
- - reachable-time
- validators: []
- spec:
- default: unspecified
- description: Reachable Time (in milliseconds) advertised in Router
- Advertisement messages
- required: false
- - name: retransmission-timer
- type: string
- profiles:
- - xpath:
- - retransmission-timer
- validators: []
- spec:
- default: unspecified
- description: Retransmission Timer (in milliseconds) advertised
- in Router Advertisement messages
- required: false
- - name: router-preference
- type: enum
- profiles:
- - xpath:
- - router-preference
- validators:
- - type: values
- spec:
- values:
- - High
- - Medium
- - Low
- spec:
- default: Medium
- values:
- - value: High
- - value: Medium
- - value: Low
- description: Router Preference
- required: false
- variants: []
- description: Router Advertisement configuration
- required: false
- variants: []
- description: Neighbor Discovery configuration
- required: false
- - name: dhcp-client
- type: object
- profiles:
- - xpath:
- - dhcp-client
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec:
- params:
- - name: accept-ra-route
- type: bool
- profiles:
- - xpath:
- - accept-ra-route
- validators: []
- spec: {}
- description: Accept Router Advertised Default Route
- required: false
- - name: default-route-metric
- type: int64
- profiles:
- - xpath:
- - default-route-metric
- validators:
- - type: length
- spec:
- min: 1
- max: 65535
- spec:
- default: 10
- description: Metric of the default route created
- required: false
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: Enable DHCPv6 Client
- required: false
- - name: neighbor-discovery
- type: object
- profiles:
- - xpath:
- - neighbor-discovery
- validators: []
- spec:
- params:
- - name: dad-attempts
- type: int64
- profiles:
- - xpath:
- - dad-attempts
- validators:
- - type: length
- spec:
- min: 1
- max: 10
- spec:
- default: 1
- description: Number of consecutive neighbor solicitation messages
- sent for duplicate address detection
- required: false
- - name: dns-server
- type: object
- profiles:
- - xpath:
- - dns-server
+ - dns-suffix
validators: []
spec:
params:
@@ -1456,11 +1197,11 @@ spec:
validators: []
spec:
params:
- - name: server
+ - name: suffix
type: list
profiles:
- xpath:
- - server
+ - suffix
- entry
type: entry
validators: []
@@ -1482,7 +1223,7 @@ spec:
max: 3600
spec:
default: 1200
- description: (4-3600) Lifetime in Seconds
+ description: (4-3600) lifetime in seconds
required: false
variants: []
description: ''
@@ -1494,118 +1235,33 @@ spec:
configure
required: false
variants: []
- description: DNS Recursive Name Server
+ description: Domain Search List
required: false
- - name: dns-suffix
- type: object
+ - name: enable-dad
+ type: bool
profiles:
- xpath:
- - dns-suffix
- validators: []
- spec:
- params:
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: ''
- required: false
- - name: source
- type: object
- profiles:
- - xpath:
- - source
- validators: []
- spec:
- params: []
- variants:
- - name: dhcpv6
- type: object
- profiles:
- - xpath:
- - dhcpv6
- validators: []
- spec:
- params: []
- variants: []
- description: Source from DHCPv6 Server
- required: false
- - name: manual
- type: object
- profiles:
- - xpath:
- - manual
- validators: []
- spec:
- params:
- - name: suffix
- type: list
- profiles:
- - xpath:
- - suffix
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
- spec:
- default: 1200
- description: (4-3600) lifetime in seconds
- required: false
- variants: []
- description: ''
- required: false
- variants: []
- description: Configure manually
- required: false
- description: Either source from DHCPv6 Server or manually
- configure
- required: false
- variants: []
- description: Domain Search List
- required: false
- - name: enable-dad
- type: bool
- profiles:
- - xpath:
- - enable-dad
- validators: []
- spec: {}
- description: Enable Duplicate ADdress Detection (DAD)
- required: false
- - name: enable-ndp-monitor
- type: bool
- profiles:
- - xpath:
- - enable-ndp-monitor
- validators: []
- spec: {}
- description: Enable NDP Monitoring
- required: false
- - name: neighbor
- type: list
- profiles:
- - xpath:
- - neighbor
- - entry
- type: entry
+ - enable-dad
+ validators: []
+ spec: {}
+ description: Enable Duplicate ADdress Detection (DAD)
+ required: false
+ - name: enable-ndp-monitor
+ type: bool
+ profiles:
+ - xpath:
+ - enable-ndp-monitor
+ validators: []
+ spec: {}
+ description: Enable NDP Monitoring
+ required: false
+ - name: neighbor
+ type: list
+ profiles:
+ - xpath:
+ - neighbor
+ - entry
+ type: entry
validators: []
spec:
type: object
@@ -1858,6 +1514,15 @@ spec:
variants: []
description: Configure DHCPv6 Client
required: false
+ - name: enabled
+ type: bool
+ profiles:
+ - xpath:
+ - enabled
+ validators: []
+ spec: {}
+ description: Enable IPv6 on the interface
+ required: false
- name: inherited
type: object
profiles:
@@ -2407,199 +2072,551 @@ spec:
variants: []
description: Static entries in neighbor cache
required: false
- - name: ns-interval
+ - name: ns-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ns-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 3600
+ spec:
+ default: 1
+ description: Interval (in seconds) between consecutive neighbor
+ solicitation messages
+ required: false
+ - name: reachable-time
+ type: int64
+ profiles:
+ - xpath:
+ - reachable-time
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 36000
+ spec:
+ default: 30
+ description: Time (in seconds) that the Reachable status for a
+ neighbor can be maintained
+ required: false
+ - name: router-advertisement
+ type: object
+ profiles:
+ - xpath:
+ - router-advertisement
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: enable-consistency-check
+ type: bool
+ profiles:
+ - xpath:
+ - enable-consistency-check
+ validators: []
+ spec: {}
+ description: check consistency of RA messages from other routers.
+ required: false
+ - name: hop-limit
+ type: string
+ profiles:
+ - xpath:
+ - hop-limit
+ validators: []
+ spec:
+ default: '64'
+ description: Current Hop Limit advertised in Router Advertisement
+ messages
+ required: false
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 9000
+ spec:
+ default: 1800
+ description: Router Lifetime (in seconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: link-mtu
+ type: string
+ profiles:
+ - xpath:
+ - link-mtu
+ validators: []
+ spec:
+ default: unspecified
+ description: value of MTU option in Router Advertisement messages,
+ upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
+ required: false
+ - name: managed-flag
+ type: bool
+ profiles:
+ - xpath:
+ - managed-flag
+ validators: []
+ spec: {}
+ description: Set the Managed Configuration Flag (M-bit) in
+ Router Advertisement messages
+ required: false
+ - name: max-interval
+ type: int64
+ profiles:
+ - xpath:
+ - max-interval
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 1800
+ spec:
+ default: 600
+ description: Maximum interval (seconds) between consecutive
+ unsolicited Router Advertisement messages
+ required: false
+ - name: min-interval
+ type: int64
+ profiles:
+ - xpath:
+ - min-interval
+ validators:
+ - type: length
+ spec:
+ min: 3
+ max: 1350
+ spec:
+ default: 200
+ description: Minimum interval (seconds) between consecutive
+ unsolicited Router Advertisement messages
+ required: false
+ - name: other-flag
+ type: bool
+ profiles:
+ - xpath:
+ - other-flag
+ validators: []
+ spec: {}
+ description: Set the Other Stateful Configuration Flag (O-bit)
+ in Router Advertisement messages
+ required: false
+ - name: reachable-time
+ type: string
+ profiles:
+ - xpath:
+ - reachable-time
+ validators: []
+ spec:
+ default: unspecified
+ description: Reachable Time (in milliseconds) advertised in
+ Router Advertisement messages
+ required: false
+ - name: retransmission-timer
+ type: string
+ profiles:
+ - xpath:
+ - retransmission-timer
+ validators: []
+ spec:
+ default: unspecified
+ description: Retransmission Timer (in milliseconds) advertised
+ in Router Advertisement messages
+ required: false
+ - name: router-preference
+ type: enum
+ profiles:
+ - xpath:
+ - router-preference
+ validators:
+ - type: values
+ spec:
+ values:
+ - High
+ - Medium
+ - Low
+ spec:
+ default: Medium
+ values:
+ - value: High
+ - value: Medium
+ - value: Low
+ description: Router Preference
+ required: false
+ variants: []
+ description: Router Advertisement configuration
+ required: false
+ variants: []
+ description: Neighbor Discovery configuration
+ required: false
+ variants: []
+ description: Configure to inherit properties from another interface
+ required: false
+ - name: interface-id
+ type: string
+ profiles:
+ - xpath:
+ - interface-id
+ validators: []
+ spec:
+ default: EUI-64
+ description: ''
+ required: false
+ - name: neighbor-discovery
+ type: object
+ profiles:
+ - xpath:
+ - neighbor-discovery
+ validators: []
+ spec:
+ params:
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 10
+ spec:
+ default: 1
+ description: Number of consecutive neighbor solicitation messages
+ sent for duplicate address detection
+ required: false
+ - name: enable-dad
+ type: bool
+ profiles:
+ - xpath:
+ - enable-dad
+ validators: []
+ spec: {}
+ description: Enable Duplicate ADdress Detection (DAD)
+ required: false
+ - name: enable-ndp-monitor
+ type: bool
+ profiles:
+ - xpath:
+ - enable-ndp-monitor
+ validators: []
+ spec: {}
+ description: Enable NDP Monitoring
+ required: false
+ - name: neighbor
+ type: list
+ profiles:
+ - xpath:
+ - neighbor
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: Static entries in neighbor cache
+ required: false
+ - name: ns-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ns-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 3600
+ spec:
+ default: 1
+ description: Interval (in seconds) between consecutive neighbor solicitation
+ messages
+ required: false
+ - name: reachable-time
+ type: int64
+ profiles:
+ - xpath:
+ - reachable-time
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 36000
+ spec:
+ default: 30
+ description: Time (in seconds) that the Reachable status for a neighbor
+ can be maintained
+ required: false
+ - name: router-advertisement
+ type: object
+ profiles:
+ - xpath:
+ - router-advertisement
+ validators: []
+ spec:
+ params:
+ - name: dns-support
+ type: object
+ profiles:
+ - xpath:
+ - dns-support
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: server
+ type: list
+ profiles:
+ - xpath:
+ - server
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: Router Lifetime (in seconds) advertised
+ in Router Advertisement messages
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: suffix
+ type: list
+ profiles:
+ - xpath:
+ - suffix
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: Router Lifetime (in seconds) advertised
+ in Router Advertisement messages
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: DNS configuration support
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: enable-consistency-check
+ type: bool
+ profiles:
+ - xpath:
+ - enable-consistency-check
+ validators: []
+ spec: {}
+ description: check consistency of RA messages from other routers.
+ required: false
+ - name: hop-limit
+ type: string
+ profiles:
+ - xpath:
+ - hop-limit
+ validators: []
+ spec:
+ default: '64'
+ description: Current Hop Limit advertised in Router Advertisement
+ messages
+ required: false
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 9000
+ spec:
+ default: 1800
+ description: Router Lifetime (in seconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: link-mtu
+ type: string
+ profiles:
+ - xpath:
+ - link-mtu
+ validators: []
+ spec:
+ default: unspecified
+ description: value of MTU option in Router Advertisement messages,
+ upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
+ required: false
+ - name: managed-flag
+ type: bool
+ profiles:
+ - xpath:
+ - managed-flag
+ validators: []
+ spec: {}
+ description: Set the Managed Configuration Flag (M-bit) in Router
+ Advertisement messages
+ required: false
+ - name: max-interval
type: int64
profiles:
- xpath:
- - ns-interval
+ - max-interval
validators:
- type: length
spec:
- min: 1
- max: 3600
+ min: 4
+ max: 1800
spec:
- default: 1
- description: Interval (in seconds) between consecutive neighbor
- solicitation messages
+ default: 600
+ description: Maximum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
required: false
- - name: reachable-time
+ - name: min-interval
type: int64
profiles:
- xpath:
- - reachable-time
+ - min-interval
validators:
- type: length
spec:
- min: 10
- max: 36000
+ min: 3
+ max: 1350
spec:
- default: 30
- description: Time (in seconds) that the Reachable status for a
- neighbor can be maintained
+ default: 200
+ description: Minimum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
required: false
- - name: router-advertisement
- type: object
+ - name: other-flag
+ type: bool
profiles:
- xpath:
- - router-advertisement
+ - other-flag
+ validators: []
+ spec: {}
+ description: Set the Other Stateful Configuration Flag (O-bit)
+ in Router Advertisement messages
+ required: false
+ - name: reachable-time
+ type: string
+ profiles:
+ - xpath:
+ - reachable-time
validators: []
spec:
- params:
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: ''
- required: false
- - name: enable-consistency-check
- type: bool
- profiles:
- - xpath:
- - enable-consistency-check
- validators: []
- spec: {}
- description: check consistency of RA messages from other routers.
- required: false
- - name: hop-limit
- type: string
- profiles:
- - xpath:
- - hop-limit
- validators: []
- spec:
- default: '64'
- description: Current Hop Limit advertised in Router Advertisement
- messages
- required: false
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 0
- max: 9000
- spec:
- default: 1800
- description: Router Lifetime (in seconds) advertised in Router
- Advertisement messages
- required: false
- - name: link-mtu
- type: string
- profiles:
- - xpath:
- - link-mtu
- validators: []
- spec:
- default: unspecified
- description: value of MTU option in Router Advertisement messages,
- upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
- required: false
- - name: managed-flag
- type: bool
- profiles:
- - xpath:
- - managed-flag
- validators: []
- spec: {}
- description: Set the Managed Configuration Flag (M-bit) in
- Router Advertisement messages
- required: false
- - name: max-interval
- type: int64
- profiles:
- - xpath:
- - max-interval
- validators:
- - type: length
- spec:
- min: 4
- max: 1800
- spec:
- default: 600
- description: Maximum interval (seconds) between consecutive
- unsolicited Router Advertisement messages
- required: false
- - name: min-interval
- type: int64
- profiles:
- - xpath:
- - min-interval
- validators:
- - type: length
- spec:
- min: 3
- max: 1350
- spec:
- default: 200
- description: Minimum interval (seconds) between consecutive
- unsolicited Router Advertisement messages
- required: false
- - name: other-flag
- type: bool
- profiles:
- - xpath:
- - other-flag
- validators: []
- spec: {}
- description: Set the Other Stateful Configuration Flag (O-bit)
- in Router Advertisement messages
- required: false
- - name: reachable-time
- type: string
- profiles:
- - xpath:
- - reachable-time
- validators: []
- spec:
- default: unspecified
- description: Reachable Time (in milliseconds) advertised in
- Router Advertisement messages
- required: false
- - name: retransmission-timer
- type: string
- profiles:
- - xpath:
- - retransmission-timer
- validators: []
- spec:
- default: unspecified
- description: Retransmission Timer (in milliseconds) advertised
- in Router Advertisement messages
- required: false
- - name: router-preference
- type: enum
- profiles:
- - xpath:
- - router-preference
- validators:
- - type: values
- spec:
- values:
- - High
- - Medium
- - Low
- spec:
- default: Medium
- values:
- - value: High
- - value: Medium
- - value: Low
- description: Router Preference
- required: false
- variants: []
- description: Router Advertisement configuration
+ default: unspecified
+ description: Reachable Time (in milliseconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: retransmission-timer
+ type: string
+ profiles:
+ - xpath:
+ - retransmission-timer
+ validators: []
+ spec:
+ default: unspecified
+ description: Retransmission Timer (in milliseconds) advertised
+ in Router Advertisement messages
+ required: false
+ - name: router-preference
+ type: enum
+ profiles:
+ - xpath:
+ - router-preference
+ validators:
+ - type: values
+ spec:
+ values:
+ - High
+ - Medium
+ - Low
+ spec:
+ default: Medium
+ values:
+ - value: High
+ - value: Medium
+ - value: Low
+ description: Router Preference
required: false
variants: []
- description: Neighbor Discovery configuration
+ description: Router Advertisement configuration
required: false
variants: []
- description: Configure to inherit properties from another interface
+ description: Neighbor Discovery configuration
required: false
variants: []
description: Interface IPv6 configuration
@@ -2945,6 +2962,7 @@ spec:
variants: []
description: DDNS derives upstream NAT IP
required: false
+ variant_group_id: 0
- name: static-ip
type: object
profiles:
@@ -2966,6 +2984,7 @@ spec:
spec: {}
description: Upstream NAT address FQDN name configuration
required: false
+ variant_group_id: 0
- name: ip-address
type: string
profiles:
@@ -2975,47 +2994,39 @@ spec:
spec: {}
description: Upstream NAT IP address
required: false
+ variant_group_id: 0
description: Upstream NAT IP address
required: false
+ variant_group_id: 0
description: Upstream NAT IP config
required: false
variants: []
description: Sdwan related settings
required: false
- - name: untagged-sub-interface
- type: bool
- profiles:
- - xpath:
- - untagged-sub-interface
- validators: []
- spec: {}
- description: Enable untagged sub-interface
- required: false
- - name: cluster-interconnect
+ - name: traffic-interconnect
type: bool
profiles:
- xpath:
- - cluster-interconnect
+ - traffic-interconnect
min_version: 11.0.2
max_version: 11.0.3
validators: []
spec: {}
description: ''
required: false
- - name: traffic-interconnect
+ - name: untagged-sub-interface
type: bool
profiles:
- xpath:
- - traffic-interconnect
- min_version: 11.0.2
- max_version: 11.0.3
+ - untagged-sub-interface
validators: []
spec: {}
- description: ''
+ description: Enable untagged sub-interface
required: false
variants: []
description: Layer 3 interface
required: false
+ variant_group_id: 0
- name: log-card
type: object
profiles:
@@ -3072,6 +3083,7 @@ spec:
variants: []
description: log card parameters
required: false
+ variant_group_id: 0
- name: tap
type: object
profiles:
@@ -3095,6 +3107,7 @@ spec:
variants: []
description: Tap mode interface
required: false
+ variant_group_id: 0
- name: virtual-wire
type: object
profiles:
@@ -3199,3 +3212,4 @@ spec:
variants: []
description: Virtual-wire interface
required: false
+ variant_group_id: 0
diff --git a/specs/network/interface/loopback.yaml b/specs/network/interface/loopback.yaml
index 736835d7..8873d770 100644
--- a/specs/network/interface/loopback.yaml
+++ b/specs/network/interface/loopback.yaml
@@ -16,11 +16,13 @@ go_sdk_config:
- network
- interface
- loopback
-xpath_suffix:
-- network
-- interface
-- loopback
-- units
+panos_xpath:
+ path:
+ - network
+ - interface
+ - loopback
+ - units
+ vars: []
locations:
- name: ngfw
xpath:
diff --git a/specs/network/interface/tunnel.yaml b/specs/network/interface/tunnel.yaml
index b019aeb5..25c6025b 100644
--- a/specs/network/interface/tunnel.yaml
+++ b/specs/network/interface/tunnel.yaml
@@ -16,11 +16,13 @@ go_sdk_config:
- network
- interface
- tunnel
-xpath_suffix:
-- network
-- interface
-- tunnel
-- units
+panos_xpath:
+ path:
+ - network
+ - interface
+ - tunnel
+ - units
+ vars: []
locations:
- name: shared
xpath:
diff --git a/specs/network/interface/vlan.yaml b/specs/network/interface/vlan.yaml
index 203cc2e7..01593489 100644
--- a/specs/network/interface/vlan.yaml
+++ b/specs/network/interface/vlan.yaml
@@ -16,11 +16,13 @@ go_sdk_config:
- network
- interface
- vlan
-xpath_suffix:
-- network
-- interface
-- vlan
-- units
+panos_xpath:
+ path:
+ - network
+ - interface
+ - vlan
+ - units
+ vars: []
locations:
- name: shared
xpath:
@@ -624,135 +626,76 @@ spec:
variants: []
description: ''
required: false
- - name: enabled
- type: bool
- profiles:
- - xpath:
- - enabled
- validators: []
- spec: {}
- description: Enable IPv6 on the interface
- required: false
- - name: interface-id
- type: string
- profiles:
- - xpath:
- - interface-id
- validators: []
- spec:
- default: EUI-64
- description: ''
- required: false
- - name: neighbor-discovery
+ - name: dhcp-client
type: object
profiles:
- xpath:
- - neighbor-discovery
+ - dhcp-client
+ min_version: 11.0.2
+ max_version: 11.0.3
validators: []
spec:
params:
- - name: dad-attempts
- type: int64
- profiles:
- - xpath:
- - dad-attempts
- validators:
- - type: length
- spec:
- min: 0
- max: 10
- spec:
- default: 1
- description: number of consecutive neighbor solicitation messages sent
- for duplicate address detection
- required: false
- - name: enable-dad
- type: bool
- profiles:
- - xpath:
- - enable-dad
- validators: []
- spec: {}
- description: enable duplicate address detection
- required: false
- - name: enable-ndp-monitor
+ - name: accept-ra-route
type: bool
profiles:
- xpath:
- - enable-ndp-monitor
+ - accept-ra-route
validators: []
spec: {}
- description: enable ndp monitoring
- required: false
- - name: neighbor
- type: list
- profiles:
- - xpath:
- - neighbor
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: hw-address
- type: string
- profiles:
- - xpath:
- - hw-address
- validators: []
- spec: {}
- description: MAC address (format xx:xx:xx:xx:xx:xx)
- required: false
- variants: []
- description: ''
+ description: Accept Router Advertised Default Route
required: false
- - name: ns-interval
+ - name: default-route-metric
type: int64
profiles:
- xpath:
- - ns-interval
+ - default-route-metric
validators:
- type: length
spec:
min: 1
- max: 3600
+ max: 65535
spec:
- default: 1
- description: interval (in seconds) between consecutive neighbor solicitation
- messages
+ default: 10
+ description: Metric of the default route created
required: false
- - name: reachable-time
- type: int64
+ - name: enable
+ type: bool
profiles:
- xpath:
- - reachable-time
- validators:
- - type: length
- spec:
- min: 10
- max: 36000
- spec:
- default: 30
- description: time (in seconds) that the Reachable status for a neighbor
- can be maintained
+ - enable
+ validators: []
+ spec: {}
+ description: Enable DHCPv6 Client
required: false
- - name: router-advertisement
+ - name: neighbor-discovery
type: object
profiles:
- xpath:
- - router-advertisement
+ - neighbor-discovery
validators: []
spec:
params:
- - name: dns-support
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 10
+ spec:
+ default: 1
+ description: number of consecutive neighbor solicitation messages
+ sent for duplicate address detection
+ required: false
+ - name: dns-server
type: object
profiles:
- xpath:
- - dns-support
+ - dns-server
validators: []
spec:
params:
@@ -765,727 +708,427 @@ spec:
spec: {}
description: ''
required: false
- - name: server
- type: list
+ - name: source
+ type: object
profiles:
- xpath:
- - server
- - entry
- type: entry
+ - source
validators: []
spec:
- type: object
- items:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
spec:
params:
- - name: lifetime
- type: int64
+ - name: server
+ type: list
profiles:
- xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
+ - server
+ - entry
+ type: entry
+ validators: []
spec:
- default: 1200
- description: (4-3600) lifetime in seconds
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) Lifetime in Seconds
+ required: false
+ variants: []
+ description: ''
required: false
variants: []
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually configure
+ required: false
+ variants: []
+ description: DNS Recursive Name Server
+ required: false
+ - name: dns-suffix
+ type: object
+ profiles:
+ - xpath:
+ - dns-suffix
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
description: ''
required: false
- - name: suffix
- type: list
+ - name: source
+ type: object
profiles:
- xpath:
- - suffix
- - entry
- type: entry
+ - source
validators: []
spec:
- type: object
- items:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
spec:
params:
- - name: lifetime
- type: int64
+ - name: suffix
+ type: list
profiles:
- xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
+ - suffix
+ - entry
+ type: entry
+ validators: []
spec:
- default: 1200
- description: (4-3600) lifetime in seconds
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
required: false
variants: []
- description: ''
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually configure
required: false
variants: []
- description: DNS configuration support
+ description: Domain Search List
required: false
- - name: enable
+ - name: enable-dad
type: bool
profiles:
- xpath:
- - enable
+ - enable-dad
validators: []
spec: {}
- description: ''
+ description: Enable Duplicate Address Detection
required: false
- - name: enable-consistency-check
+ - name: enable-ndp-monitor
type: bool
profiles:
- xpath:
- - enable-consistency-check
+ - enable-ndp-monitor
validators: []
spec: {}
- description: check consistency of RA messages from other routers.
+ description: Enable NDP Monitoring
required: false
- - name: hop-limit
- type: string
+ - name: neighbor
+ type: list
profiles:
- xpath:
- - hop-limit
+ - neighbor
+ - entry
+ type: entry
validators: []
spec:
- default: '64'
- description: Current Hop Limit advertised in Router Advertisement
- messages
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
required: false
- - name: lifetime
+ - name: ns-interval
type: int64
profiles:
- xpath:
- - lifetime
+ - ns-interval
validators:
- type: length
spec:
- min: 0
- max: 9000
+ min: 1
+ max: 3600
spec:
- default: 1800
- description: Router Lifetime (in seconds) advertised in Router Advertisement
+ default: 1
+ description: interval (in seconds) between consecutive neighbor solicitation
messages
required: false
- - name: link-mtu
- type: string
- profiles:
- - xpath:
- - link-mtu
- validators: []
- spec:
- default: unspecified
- description: value of MTU option in Router Advertisement messages,
- upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
- required: false
- - name: managed-flag
- type: bool
- profiles:
- - xpath:
- - managed-flag
- validators: []
- spec: {}
- description: Set the Managed Configuration Flag (M-bit) in Router
- Advertisement messages
- required: false
- - name: max-interval
- type: int64
- profiles:
- - xpath:
- - max-interval
- validators:
- - type: length
- spec:
- min: 4
- max: 1800
- spec:
- default: 600
- description: Maximum interval (seconds) between consecutive unsolicited
- Router Advertisement messages
- required: false
- - name: min-interval
- type: int64
- profiles:
- - xpath:
- - min-interval
- validators:
- - type: length
- spec:
- min: 3
- max: 1350
- spec:
- default: 200
- description: Minimum interval (seconds) between consecutive unsolicited
- Router Advertisement messages
- required: false
- - name: other-flag
- type: bool
- profiles:
- - xpath:
- - other-flag
- validators: []
- spec: {}
- description: Set the Other Stateful Configuration Flag (O-bit) in
- Router Advertisement messages
- required: false
- name: reachable-time
- type: string
+ type: int64
profiles:
- xpath:
- reachable-time
- validators: []
- spec:
- default: unspecified
- description: Reachable Time (in milliseconds) advertised in Router
- Advertisement messages
- required: false
- - name: retransmission-timer
- type: string
- profiles:
- - xpath:
- - retransmission-timer
- validators: []
- spec:
- default: unspecified
- description: Retransmission Timer (in milliseconds) advertised in
- Router Advertisement messages
- required: false
- - name: router-preference
- type: enum
- profiles:
- - xpath:
- - router-preference
validators:
- - type: values
+ - type: length
spec:
- values:
- - High
- - Medium
- - Low
+ min: 10
+ max: 36000
spec:
- default: Medium
- values:
- - value: High
- - value: Medium
- - value: Low
- description: ''
+ default: 30
+ description: time (in seconds) that the Reachable status for a neighbor
+ can be maintained
required: false
variants: []
- description: Router advertisement configuration
- required: false
- variants: []
- description: Neighbor Discovery configuration
- required: false
- - name: dhcp-client
- type: object
- profiles:
- - xpath:
- - dhcp-client
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec:
- params:
- - name: accept-ra-route
- type: bool
- profiles:
- - xpath:
- - accept-ra-route
- validators: []
- spec: {}
- description: Accept Router Advertised Default Route
+ description: Neighbor Discovery configuration
required: false
- - name: default-route-metric
- type: int64
+ - name: preference
+ type: enum
profiles:
- xpath:
- - default-route-metric
+ - preference
validators:
- - type: length
+ - type: values
spec:
- min: 1
- max: 65535
+ values:
+ - low
+ - medium
+ - high
spec:
- default: 10
- description: Metric of the default route created
- required: false
- - name: enable
- type: bool
- profiles:
- - xpath:
- - enable
- validators: []
- spec: {}
- description: Enable DHCPv6 Client
+ default: high
+ values:
+ - value: low
+ - value: medium
+ - value: high
+ description: Select Low/Medium/High
required: false
- - name: neighbor-discovery
+ - name: prefix-delegation
type: object
profiles:
- xpath:
- - neighbor-discovery
+ - prefix-delegation
validators: []
spec:
params:
- - name: dad-attempts
- type: int64
+ - name: enable
+ type: object
profiles:
- xpath:
- - dad-attempts
- validators:
- - type: length
- spec:
- min: 1
- max: 10
- spec:
- default: 1
- description: number of consecutive neighbor solicitation messages
- sent for duplicate address detection
- required: false
- - name: dns-server
- type: object
- profiles:
- - xpath:
- - dns-server
+ - enable
validators: []
spec:
- params:
- - name: enable
- type: bool
+ params: []
+ variants:
+ - name: 'no'
+ type: object
profiles:
- xpath:
- - enable
+ - 'no'
validators: []
- spec: {}
- description: ''
+ spec:
+ params: []
+ variants: []
+ description: Disable Prefix Delegation
required: false
- - name: source
+ - name: 'yes'
type: object
profiles:
- xpath:
- - source
+ - 'yes'
validators: []
spec:
- params: []
- variants:
- - name: dhcpv6
- type: object
+ params:
+ - name: pfx-pool-name
+ type: string
profiles:
- xpath:
- - dhcpv6
- validators: []
+ - pfx-pool-name
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Configure unique Prefix Pool Name
+ required: false
+ - name: prefix-len
+ type: int64
+ profiles:
+ - xpath:
+ - prefix-len
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 128
spec:
- params: []
- variants: []
- description: Source from DHCPv6 Server
+ default: 48
+ description: Hint DHCP Prefix Length (bits)
required: false
- - name: manual
- type: object
+ - name: prefix-len-hint
+ type: bool
profiles:
- xpath:
- - manual
+ - prefix-len-hint
validators: []
- spec:
- params:
- - name: server
- type: list
- profiles:
- - xpath:
- - server
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
- spec:
- default: 1200
- description: (4-3600) Lifetime in Seconds
- required: false
- variants: []
- description: ''
- required: false
- variants: []
- description: Configure manually
+ spec: {}
+ description: Send prefix length hint to server
required: false
- description: Either source from DHCPv6 Server or manually configure
+ variants: []
+ description: Enable Prefix Delegation
required: false
- variants: []
- description: DNS Recursive Name Server
+ description: Enable/Disable Prefix Delegation
required: false
- - name: dns-suffix
+ variants: []
+ description: Configure Prefix Delegation Options
+ required: false
+ - name: v6-options
+ type: object
+ profiles:
+ - xpath:
+ - v6-options
+ validators: []
+ spec:
+ params:
+ - name: duid-type
+ type: enum
+ profiles:
+ - xpath:
+ - duid-type
+ validators:
+ - type: values
+ spec:
+ values:
+ - duid-type-llt
+ - duid-type-ll
+ spec:
+ default: duid-type-llt
+ values:
+ - value: duid-type-llt
+ - value: duid-type-ll
+ description: Select DUID-LLT/DUID-LL
+ required: false
+ - name: enable
type: object
profiles:
- xpath:
- - dns-suffix
+ - enable
validators: []
spec:
- params:
- - name: enable
- type: bool
+ params: []
+ variants:
+ - name: 'no'
+ type: object
profiles:
- xpath:
- - enable
+ - 'no'
validators: []
- spec: {}
- description: ''
+ spec:
+ params: []
+ variants: []
+ description: Disable IPv6 Address
required: false
- - name: source
+ - name: 'yes'
type: object
profiles:
- xpath:
- - source
+ - 'yes'
validators: []
spec:
- params: []
- variants:
- - name: dhcpv6
- type: object
+ params:
+ - name: non-temp-addr
+ type: bool
profiles:
- xpath:
- - dhcpv6
+ - non-temp-addr
validators: []
- spec:
- params: []
- variants: []
- description: Source from DHCPv6 Server
+ spec: {}
+ description: Request Non-Temporary Address Type
required: false
- - name: manual
- type: object
+ - name: temp-addr
+ type: bool
profiles:
- xpath:
- - manual
+ - temp-addr
validators: []
- spec:
- params:
- - name: suffix
- type: list
- profiles:
- - xpath:
- - suffix
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: lifetime
- type: int64
- profiles:
- - xpath:
- - lifetime
- validators:
- - type: length
- spec:
- min: 4
- max: 3600
- spec:
- default: 1200
- description: (4-3600) lifetime in seconds
- required: false
- variants: []
- description: ''
- required: false
- variants: []
- description: Configure manually
+ spec: {}
+ description: Request Temporary Address Type
required: false
- description: Either source from DHCPv6 Server or manually configure
+ variants: []
+ description: Enable IPv6 Address
required: false
- variants: []
- description: Domain Search List
+ description: Enable/Disable IPv6 Address
required: false
- - name: enable-dad
+ - name: rapid-commit
type: bool
profiles:
- xpath:
- - enable-dad
+ - rapid-commit
validators: []
spec: {}
- description: Enable Duplicate Address Detection
+ description: Enable Rapid Commit
required: false
- - name: enable-ndp-monitor
+ - name: support-srvr-reconfig
type: bool
profiles:
- xpath:
- - enable-ndp-monitor
+ - support-srvr-reconfig
validators: []
spec: {}
- description: Enable NDP Monitoring
- required: false
- - name: neighbor
- type: list
- profiles:
- - xpath:
- - neighbor
- - entry
- type: entry
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: hw-address
- type: string
- profiles:
- - xpath:
- - hw-address
- validators: []
- spec: {}
- description: MAC address (format xx:xx:xx:xx:xx:xx)
- required: false
- variants: []
- description: ''
- required: false
- - name: ns-interval
- type: int64
- profiles:
- - xpath:
- - ns-interval
- validators:
- - type: length
- spec:
- min: 1
- max: 3600
- spec:
- default: 1
- description: interval (in seconds) between consecutive neighbor solicitation
- messages
- required: false
- - name: reachable-time
- type: int64
- profiles:
- - xpath:
- - reachable-time
- validators:
- - type: length
- spec:
- min: 10
- max: 36000
- spec:
- default: 30
- description: time (in seconds) that the Reachable status for a neighbor
- can be maintained
- required: false
- variants: []
- description: Neighbor Discovery configuration
- required: false
- - name: preference
- type: enum
- profiles:
- - xpath:
- - preference
- validators:
- - type: values
- spec:
- values:
- - low
- - medium
- - high
- spec:
- default: high
- values:
- - value: low
- - value: medium
- - value: high
- description: Select Low/Medium/High
- required: false
- - name: prefix-delegation
- type: object
- profiles:
- - xpath:
- - prefix-delegation
- validators: []
- spec:
- params:
- - name: enable
- type: object
- profiles:
- - xpath:
- - enable
- validators: []
- spec:
- params: []
- variants:
- - name: 'no'
- type: object
- profiles:
- - xpath:
- - 'no'
- validators: []
- spec:
- params: []
- variants: []
- description: Disable Prefix Delegation
- required: false
- - name: 'yes'
- type: object
- profiles:
- - xpath:
- - 'yes'
- validators: []
- spec:
- params:
- - name: pfx-pool-name
- type: string
- profiles:
- - xpath:
- - pfx-pool-name
- validators:
- - type: length
- spec:
- max: 63
- spec: {}
- description: Configure unique Prefix Pool Name
- required: false
- - name: prefix-len
- type: int64
- profiles:
- - xpath:
- - prefix-len
- validators:
- - type: length
- spec:
- min: 0
- max: 128
- spec:
- default: 48
- description: Hint DHCP Prefix Length (bits)
- required: false
- - name: prefix-len-hint
- type: bool
- profiles:
- - xpath:
- - prefix-len-hint
- validators: []
- spec: {}
- description: Send prefix length hint to server
- required: false
- variants: []
- description: Enable Prefix Delegation
- required: false
- description: Enable/Disable Prefix Delegation
- required: false
- variants: []
- description: Configure Prefix Delegation Options
- required: false
- - name: v6-options
- type: object
- profiles:
- - xpath:
- - v6-options
- validators: []
- spec:
- params:
- - name: duid-type
- type: enum
- profiles:
- - xpath:
- - duid-type
- validators:
- - type: values
- spec:
- values:
- - duid-type-llt
- - duid-type-ll
- spec:
- default: duid-type-llt
- values:
- - value: duid-type-llt
- - value: duid-type-ll
- description: Select DUID-LLT/DUID-LL
- required: false
- - name: enable
- type: object
- profiles:
- - xpath:
- - enable
- validators: []
- spec:
- params: []
- variants:
- - name: 'no'
- type: object
- profiles:
- - xpath:
- - 'no'
- validators: []
- spec:
- params: []
- variants: []
- description: Disable IPv6 Address
- required: false
- - name: 'yes'
- type: object
- profiles:
- - xpath:
- - 'yes'
- validators: []
- spec:
- params:
- - name: non-temp-addr
- type: bool
- profiles:
- - xpath:
- - non-temp-addr
- validators: []
- spec: {}
- description: Request Non-Temporary Address Type
- required: false
- - name: temp-addr
- type: bool
- profiles:
- - xpath:
- - temp-addr
- validators: []
- spec: {}
- description: Request Temporary Address Type
- required: false
- variants: []
- description: Enable IPv6 Address
- required: false
- description: Enable/Disable IPv6 Address
- required: false
- - name: rapid-commit
- type: bool
- profiles:
- - xpath:
- - rapid-commit
- validators: []
- spec: {}
- description: Enable Rapid Commit
- required: false
- - name: support-srvr-reconfig
- type: bool
- profiles:
- - xpath:
- - support-srvr-reconfig
- validators: []
- spec: {}
- description: Enable DHCPv6 Server Re-Configuration Support
+ description: Enable DHCPv6 Server Re-Configuration Support
required: false
variants: []
description: Configure DHCPv6 Options
@@ -1493,6 +1136,15 @@ spec:
variants: []
description: Configure DHCPv6 Client
required: false
+ - name: enabled
+ type: bool
+ profiles:
+ - xpath:
+ - enabled
+ validators: []
+ spec: {}
+ description: Enable IPv6 on the interface
+ required: false
- name: inherited
type: object
profiles:
@@ -2225,6 +1877,356 @@ spec:
variants: []
description: Configure to inherit properties from another interface
required: false
+ - name: interface-id
+ type: string
+ profiles:
+ - xpath:
+ - interface-id
+ validators: []
+ spec:
+ default: EUI-64
+ description: ''
+ required: false
+ - name: neighbor-discovery
+ type: object
+ profiles:
+ - xpath:
+ - neighbor-discovery
+ validators: []
+ spec:
+ params:
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 10
+ spec:
+ default: 1
+ description: number of consecutive neighbor solicitation messages sent
+ for duplicate address detection
+ required: false
+ - name: enable-dad
+ type: bool
+ profiles:
+ - xpath:
+ - enable-dad
+ validators: []
+ spec: {}
+ description: enable duplicate address detection
+ required: false
+ - name: enable-ndp-monitor
+ type: bool
+ profiles:
+ - xpath:
+ - enable-ndp-monitor
+ validators: []
+ spec: {}
+ description: enable ndp monitoring
+ required: false
+ - name: neighbor
+ type: list
+ profiles:
+ - xpath:
+ - neighbor
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: ns-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ns-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 3600
+ spec:
+ default: 1
+ description: interval (in seconds) between consecutive neighbor solicitation
+ messages
+ required: false
+ - name: reachable-time
+ type: int64
+ profiles:
+ - xpath:
+ - reachable-time
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 36000
+ spec:
+ default: 30
+ description: time (in seconds) that the Reachable status for a neighbor
+ can be maintained
+ required: false
+ - name: router-advertisement
+ type: object
+ profiles:
+ - xpath:
+ - router-advertisement
+ validators: []
+ spec:
+ params:
+ - name: dns-support
+ type: object
+ profiles:
+ - xpath:
+ - dns-support
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: server
+ type: list
+ profiles:
+ - xpath:
+ - server
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: suffix
+ type: list
+ profiles:
+ - xpath:
+ - suffix
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: DNS configuration support
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: enable-consistency-check
+ type: bool
+ profiles:
+ - xpath:
+ - enable-consistency-check
+ validators: []
+ spec: {}
+ description: check consistency of RA messages from other routers.
+ required: false
+ - name: hop-limit
+ type: string
+ profiles:
+ - xpath:
+ - hop-limit
+ validators: []
+ spec:
+ default: '64'
+ description: Current Hop Limit advertised in Router Advertisement
+ messages
+ required: false
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 9000
+ spec:
+ default: 1800
+ description: Router Lifetime (in seconds) advertised in Router Advertisement
+ messages
+ required: false
+ - name: link-mtu
+ type: string
+ profiles:
+ - xpath:
+ - link-mtu
+ validators: []
+ spec:
+ default: unspecified
+ description: value of MTU option in Router Advertisement messages,
+ upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
+ required: false
+ - name: managed-flag
+ type: bool
+ profiles:
+ - xpath:
+ - managed-flag
+ validators: []
+ spec: {}
+ description: Set the Managed Configuration Flag (M-bit) in Router
+ Advertisement messages
+ required: false
+ - name: max-interval
+ type: int64
+ profiles:
+ - xpath:
+ - max-interval
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 1800
+ spec:
+ default: 600
+ description: Maximum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: min-interval
+ type: int64
+ profiles:
+ - xpath:
+ - min-interval
+ validators:
+ - type: length
+ spec:
+ min: 3
+ max: 1350
+ spec:
+ default: 200
+ description: Minimum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: other-flag
+ type: bool
+ profiles:
+ - xpath:
+ - other-flag
+ validators: []
+ spec: {}
+ description: Set the Other Stateful Configuration Flag (O-bit) in
+ Router Advertisement messages
+ required: false
+ - name: reachable-time
+ type: string
+ profiles:
+ - xpath:
+ - reachable-time
+ validators: []
+ spec:
+ default: unspecified
+ description: Reachable Time (in milliseconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: retransmission-timer
+ type: string
+ profiles:
+ - xpath:
+ - retransmission-timer
+ validators: []
+ spec:
+ default: unspecified
+ description: Retransmission Timer (in milliseconds) advertised in
+ Router Advertisement messages
+ required: false
+ - name: router-preference
+ type: enum
+ profiles:
+ - xpath:
+ - router-preference
+ validators:
+ - type: values
+ spec:
+ values:
+ - High
+ - Medium
+ - Low
+ spec:
+ default: Medium
+ values:
+ - value: High
+ - value: Medium
+ - value: Low
+ description: ''
+ required: false
+ variants: []
+ description: Router advertisement configuration
+ required: false
+ variants: []
+ description: Neighbor Discovery configuration
+ required: false
variants: []
description: Interface IPv6 configuration
required: false
diff --git a/specs/network/logical-router.yaml b/specs/network/logical-router.yaml
index 08ab1ac2..8a2d1d6c 100644
--- a/specs/network/logical-router.yaml
+++ b/specs/network/logical-router.yaml
@@ -15,9 +15,11 @@ go_sdk_config:
package:
- network
- logical_router
-xpath_suffix:
-- network
-- logical-router
+panos_xpath:
+ path:
+ - network
+ - logical-router
+ vars: []
locations:
- name: vsys
xpath:
diff --git a/specs/network/profiles/anti-spyware-profile.yaml b/specs/network/profiles/anti-spyware-profile.yaml
index 254effb1..28607082 100644
--- a/specs/network/profiles/anti-spyware-profile.yaml
+++ b/specs/network/profiles/anti-spyware-profile.yaml
@@ -16,9 +16,11 @@ go_sdk_config:
- security
- profiles
- spyware
-xpath_suffix:
-- profiles
-- spyware
+panos_xpath:
+ path:
+ - profiles
+ - spyware
+ vars: []
locations:
- name: shared
xpath:
@@ -62,7 +64,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
@@ -292,6 +293,73 @@ spec:
variants: []
description: ''
required: false
+ - name: rtype-action
+ type: object
+ profiles:
+ - xpath:
+ - rtype-action
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec:
+ params:
+ - name: any
+ type: enum
+ profiles:
+ - xpath:
+ - any
+ validators:
+ - type: values
+ spec:
+ values:
+ - allow
+ - block
+ spec:
+ default: allow
+ values:
+ - value: allow
+ - value: block
+ description: ANY(255)
+ required: false
+ - name: https
+ type: enum
+ profiles:
+ - xpath:
+ - https
+ validators:
+ - type: values
+ spec:
+ values:
+ - allow
+ - block
+ spec:
+ default: allow
+ values:
+ - value: allow
+ - value: block
+ description: HTTPS(65)
+ required: false
+ - name: svcb
+ type: enum
+ profiles:
+ - xpath:
+ - svcb
+ validators:
+ - type: values
+ spec:
+ values:
+ - allow
+ - block
+ spec:
+ default: allow
+ values:
+ - value: allow
+ - value: block
+ description: SVCB(64)
+ required: false
+ variants: []
+ description: Action for specific record types
+ required: false
- name: sinkhole
type: object
profiles:
@@ -370,73 +438,6 @@ spec:
variants: []
description: ''
required: false
- - name: rtype-action
- type: object
- profiles:
- - xpath:
- - rtype-action
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec:
- params:
- - name: any
- type: enum
- profiles:
- - xpath:
- - any
- validators:
- - type: values
- spec:
- values:
- - allow
- - block
- spec:
- default: allow
- values:
- - value: allow
- - value: block
- description: ANY(255)
- required: false
- - name: https
- type: enum
- profiles:
- - xpath:
- - https
- validators:
- - type: values
- spec:
- values:
- - allow
- - block
- spec:
- default: allow
- values:
- - value: allow
- - value: block
- description: HTTPS(65)
- required: false
- - name: svcb
- type: enum
- profiles:
- - xpath:
- - svcb
- validators:
- - type: values
- spec:
- values:
- - allow
- - block
- spec:
- default: allow
- values:
- - value: allow
- - value: block
- description: SVCB(64)
- required: false
- variants: []
- description: Action for specific record types
- required: false
variants: []
description: ''
required: false
diff --git a/specs/network/profiles/interface-management-profile.yaml b/specs/network/profiles/interface-management-profile.yaml
index c5edeca3..6a42408b 100644
--- a/specs/network/profiles/interface-management-profile.yaml
+++ b/specs/network/profiles/interface-management-profile.yaml
@@ -15,10 +15,12 @@ go_sdk_config:
- network
- profiles
- interface_management
-xpath_suffix:
-- network
-- profiles
-- interface-management-profile
+panos_xpath:
+ path:
+ - network
+ - profiles
+ - interface-management-profile
+ vars: []
locations:
- name: ngfw
xpath:
diff --git a/specs/network/subinterface/ethernet/layer3.yaml b/specs/network/subinterface/ethernet/layer3.yaml
new file mode 100644
index 00000000..38683048
--- /dev/null
+++ b/specs/network/subinterface/ethernet/layer3.yaml
@@ -0,0 +1,2632 @@
+name: ethernet-layer3-subinterface
+terraform_provider_config:
+ description: Ethernet Layer3 Subinterface
+ skip_resource: false
+ skip_datasource: false
+ resource_type: entry
+ resource_variants:
+ - singular
+ suffix: ethernet_layer3_subinterface
+ plural_suffix: ''
+ plural_name: ''
+ plural_description: ''
+go_sdk_config:
+ skip: false
+ package:
+ - network
+ - interface
+ - ethernet
+ - subinterface
+ - layer3
+panos_xpath:
+ path:
+ - network
+ - interface
+ - ethernet
+ - $parent
+ - layer3
+ - units
+ - $name
+ vars:
+ - name: parent
+ spec:
+ type: entry
+ xpath: /params[@name="parent"]
+ - name: name
+ spec:
+ type: entry
+ xpath: /params[@name="name"]
+locations:
+- name: shared
+ xpath:
+ path:
+ - config
+ - shared
+ vars: []
+ description: Panorama shared object
+ devices:
+ - panorama
+ - ngfw
+ validators: []
+ required: false
+ read_only: false
+- name: template
+ xpath:
+ path:
+ - config
+ - devices
+ - $panorama_device
+ - template
+ - $template
+ - config
+ - devices
+ - $ngfw_device
+ vars:
+ - name: panorama_device
+ description: Specific Panorama device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ - name: template
+ description: Specific Panorama template
+ required: true
+ validators: []
+ type: entry
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ description: Located in a specific template
+ devices:
+ - panorama
+ validators: []
+ required: false
+ read_only: false
+- name: template-stack
+ xpath:
+ path:
+ - config
+ - devices
+ - $panorama_device
+ - template-stack
+ - $template_stack
+ - config
+ - devices
+ - $ngfw_device
+ vars:
+ - name: panorama_device
+ description: Specific Panorama device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ - name: template_stack
+ description: Specific Panorama template stack
+ required: true
+ validators: []
+ type: entry
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ description: Located in a specific template stack
+ devices:
+ - panorama
+ validators: []
+ required: false
+ read_only: false
+- name: ngfw
+ xpath:
+ path:
+ - config
+ - devices
+ - $ngfw_device
+ vars:
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ description: Located in a specific NGFW device
+ devices:
+ - ngfw
+ validators: []
+ required: false
+ read_only: false
+entries:
+- name: name
+ description: ''
+ validators: []
+imports:
+- variant: ''
+ type: template
+ locations:
+ - name: vsys
+ xpath:
+ path:
+ - vsys
+ - $vsys
+ - import
+ - network
+ - interface
+ vars:
+ - name: vsys
+ description: The vsys.
+ required: false
+ default: vsys1
+ validators: []
+ type: entry
+ description: ''
+ validators: []
+ required: true
+ read_only: false
+spec:
+ params:
+ - name: parent
+ type: string
+ profiles:
+ - xpath: []
+ codegen_overrides:
+ gosdk:
+ skip: true
+ terraform:
+ xpath_variable: parent
+ - name: adjust-tcp-mss
+ type: object
+ profiles:
+ - xpath:
+ - adjust-tcp-mss
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Set if TCP MSS value should be reduced based on mtu
+ required: false
+ - name: ipv4-mss-adjustment
+ type: int64
+ profiles:
+ - xpath:
+ - ipv4-mss-adjustment
+ validators:
+ - type: length
+ spec:
+ min: 40
+ max: 300
+ spec:
+ default: 40
+ description: IPv4 MSS adjustment size (in bytes)
+ required: false
+ - name: ipv6-mss-adjustment
+ type: int64
+ profiles:
+ - xpath:
+ - ipv6-mss-adjustment
+ validators:
+ - type: length
+ spec:
+ min: 60
+ max: 300
+ spec:
+ default: 60
+ description: IPv6 MSS adjustment size (in bytes)
+ required: false
+ variants: []
+ description: TCP MSS adjustment configuration
+ required: false
+ - name: arp
+ type: list
+ profiles:
+ - xpath:
+ - arp
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: bonjour
+ type: object
+ profiles:
+ - xpath:
+ - bonjour
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Set to support Bonjour service
+ required: false
+ - name: group-id
+ type: int64
+ profiles:
+ - xpath:
+ - group-id
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 16
+ spec:
+ default: 40
+ description: 'default 0: NO-Group'
+ required: false
+ - name: ttl-check
+ type: bool
+ profiles:
+ - xpath:
+ - ttl-check
+ validators: []
+ spec: {}
+ description: Set to check and update TTL
+ required: false
+ variants: []
+ description: Bonjour configuration
+ required: false
+ - name: comment
+ type: string
+ profiles:
+ - xpath:
+ - comment
+ validators:
+ - type: length
+ spec:
+ max: 1024
+ spec: {}
+ description: ''
+ required: false
+ - name: ddns-config
+ type: object
+ profiles:
+ - xpath:
+ - ddns-config
+ validators: []
+ spec:
+ params:
+ - name: ddns-cert-profile
+ type: string
+ profiles:
+ - xpath:
+ - ddns-cert-profile
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: ddns-enabled
+ type: bool
+ profiles:
+ - xpath:
+ - ddns-enabled
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: ddns-hostname
+ type: string
+ profiles:
+ - xpath:
+ - ddns-hostname
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 255
+ spec: {}
+ description: ddns hostname variable or real address
+ required: false
+ - name: ddns-ip
+ type: list
+ profiles:
+ - xpath:
+ - ddns-ip
+ type: member
+ validators: []
+ spec:
+ type: string
+ items:
+ type: string
+ description: ''
+ required: false
+ - name: ddns-ipv6
+ type: list
+ profiles:
+ - xpath:
+ - ddns-ipv6
+ type: member
+ validators: []
+ spec:
+ type: string
+ items:
+ type: string
+ description: ''
+ required: false
+ - name: ddns-update-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ddns-update-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 30
+ spec:
+ default: 1
+ description: ''
+ required: false
+ - name: ddns-vendor
+ type: string
+ profiles:
+ - xpath:
+ - ddns-vendor
+ validators:
+ - type: length
+ spec:
+ max: 127
+ spec: {}
+ description: Vendor and product type
+ required: false
+ - name: ddns-vendor-config
+ type: list
+ profiles:
+ - xpath:
+ - ddns-vendor-config
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: value
+ type: string
+ profiles:
+ - xpath:
+ - value
+ validators:
+ - type: length
+ spec:
+ max: 255
+ spec: {}
+ description: ''
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: decrypt-forward
+ type: bool
+ profiles:
+ - xpath:
+ - decrypt-forward
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: df-ignore
+ type: bool
+ profiles:
+ - xpath:
+ - df-ignore
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: dhcp-client
+ type: object
+ profiles:
+ - xpath:
+ - dhcp-client
+ validators: []
+ spec:
+ params:
+ - name: create-default-route
+ type: bool
+ profiles:
+ - xpath:
+ - create-default-route
+ validators: []
+ spec: {}
+ description: Automatically create default route pointing to default gateway
+ provided by server
+ required: false
+ - name: default-route-metric
+ type: int64
+ profiles:
+ - xpath:
+ - default-route-metric
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 65535
+ spec:
+ default: 10
+ description: Metric of the default route created
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: send-hostname
+ type: object
+ profiles:
+ - xpath:
+ - send-hostname
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: hostname
+ type: string
+ profiles:
+ - xpath:
+ - hostname
+ validators: []
+ spec:
+ default: system-hostname
+ description: Set Interface Hostname
+ required: false
+ variants: []
+ description: Enable send firewall or custom hostname to DHCP server
+ required: false
+ variants: []
+ description: dhcp client configuration
+ required: false
+ - name: interface-management-profile
+ type: string
+ profiles:
+ - xpath:
+ - interface-management-profile
+ validators:
+ - type: length
+ spec:
+ max: 31
+ spec: {}
+ description: Interface management profile
+ required: false
+ - name: ip
+ type: list
+ profiles:
+ - xpath:
+ - ip
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: sdwan-gateway
+ type: string
+ profiles:
+ - xpath:
+ - sdwan-gateway
+ validators: []
+ spec: {}
+ description: Gateway IPv4 Address
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: ipv6
+ type: object
+ profiles:
+ - xpath:
+ - ipv6
+ validators: []
+ spec:
+ params:
+ - name: address
+ type: list
+ profiles:
+ - xpath:
+ - address
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: enable-on-interface
+ type: bool
+ profiles:
+ - xpath:
+ - enable-on-interface
+ validators: []
+ spec: {}
+ description: configure this address on interface
+ required: false
+ - name: prefix
+ type: object
+ profiles:
+ - xpath:
+ - prefix
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: use this as prefix to form full address with interface
+ id/EUI-64
+ required: false
+ - name: anycast
+ type: object
+ profiles:
+ - xpath:
+ - anycast
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: anycast address
+ required: false
+ - name: advertise
+ type: object
+ profiles:
+ - xpath:
+ - advertise
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: enable advertising this prefix in router advertisements
+ required: false
+ - name: valid-lifetime
+ type: string
+ profiles:
+ - xpath:
+ - valid-lifetime
+ validators: []
+ spec:
+ default: '2592000'
+ description: Valid Lifetime (in seconds) of the prefix advertised
+ in Router Advertisement messages
+ required: false
+ - name: preferred-lifetime
+ type: string
+ profiles:
+ - xpath:
+ - preferred-lifetime
+ validators: []
+ spec:
+ default: '604800'
+ description: Preferred Lifetime (in seconds) of the prefix advertised
+ in Router Advertisement messages
+ required: false
+ - name: onlink-flag
+ type: bool
+ profiles:
+ - xpath:
+ - onlink-flag
+ validators: []
+ spec: {}
+ description: Set the On-Link Flag (L-bit) of the prefix in Router
+ Advertisement messages
+ required: false
+ - name: auto-config-flag
+ type: bool
+ profiles:
+ - xpath:
+ - auto-config-flag
+ validators: []
+ spec: {}
+ description: Set the Auto Address Configuration Flag (A-bit) of
+ the prefix in Router Advertisement messages
+ required: false
+ variants: []
+ description: configure router advertisement prefix option
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: dhcp-client
+ type: object
+ profiles:
+ - xpath:
+ - dhcp-client
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec:
+ params:
+ - name: accept-ra-route
+ type: bool
+ profiles:
+ - xpath:
+ - accept-ra-route
+ validators: []
+ spec: {}
+ description: Accept Router Advertised Default Route
+ required: false
+ - name: default-route-metric
+ type: int64
+ profiles:
+ - xpath:
+ - default-route-metric
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 65535
+ spec:
+ default: 10
+ description: Metric of the default route created
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable DHCPv6 Client
+ required: false
+ - name: neighbor-discovery
+ type: object
+ profiles:
+ - xpath:
+ - neighbor-discovery
+ validators: []
+ spec:
+ params:
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 10
+ spec:
+ default: 1
+ description: number of consecutive neighbor solicitation messages
+ sent for duplicate address detection
+ required: false
+ - name: dns-server
+ type: object
+ profiles:
+ - xpath:
+ - dns-server
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: source
+ type: object
+ profiles:
+ - xpath:
+ - source
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
+ type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
+ spec:
+ params:
+ - name: server
+ type: list
+ profiles:
+ - xpath:
+ - server
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) Lifetime in Seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually configure
+ required: false
+ variants: []
+ description: DNS Recursive Name Server
+ required: false
+ - name: dns-suffix
+ type: object
+ profiles:
+ - xpath:
+ - dns-suffix
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: source
+ type: object
+ profiles:
+ - xpath:
+ - source
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
+ type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
+ spec:
+ params:
+ - name: suffix
+ type: list
+ profiles:
+ - xpath:
+ - suffix
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually configure
+ required: false
+ variants: []
+ description: Domain Search List
+ required: false
+ - name: enable-dad
+ type: bool
+ profiles:
+ - xpath:
+ - enable-dad
+ validators: []
+ spec: {}
+ description: Enable Duplicate Address Detection
+ required: false
+ - name: enable-ndp-monitor
+ type: bool
+ profiles:
+ - xpath:
+ - enable-ndp-monitor
+ validators: []
+ spec: {}
+ description: Enable NDP Monitoring
+ required: false
+ - name: neighbor
+ type: list
+ profiles:
+ - xpath:
+ - neighbor
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: ns-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ns-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 3600
+ spec:
+ default: 1
+ description: interval (in seconds) between consecutive neighbor solicitation
+ messages
+ required: false
+ - name: reachable-time
+ type: int64
+ profiles:
+ - xpath:
+ - reachable-time
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 36000
+ spec:
+ default: 30
+ description: time (in seconds) that the Reachable status for a neighbor
+ can be maintained
+ required: false
+ variants: []
+ description: Neighbor Discovery configuration
+ required: false
+ - name: preference
+ type: enum
+ profiles:
+ - xpath:
+ - preference
+ validators:
+ - type: values
+ spec:
+ values:
+ - low
+ - medium
+ - high
+ spec:
+ default: high
+ values:
+ - value: low
+ - value: medium
+ - value: high
+ description: Select Low/Medium/High
+ required: false
+ - name: prefix-delegation
+ type: object
+ profiles:
+ - xpath:
+ - prefix-delegation
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: object
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: 'no'
+ type: object
+ profiles:
+ - xpath:
+ - 'no'
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Disable Prefix Delegation
+ required: false
+ - name: 'yes'
+ type: object
+ profiles:
+ - xpath:
+ - 'yes'
+ validators: []
+ spec:
+ params:
+ - name: pfx-pool-name
+ type: string
+ profiles:
+ - xpath:
+ - pfx-pool-name
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Configure unique Prefix Pool Name
+ required: false
+ - name: prefix-len
+ type: int64
+ profiles:
+ - xpath:
+ - prefix-len
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 128
+ spec:
+ default: 48
+ description: Hint DHCP Prefix Length (bits)
+ required: false
+ - name: prefix-len-hint
+ type: bool
+ profiles:
+ - xpath:
+ - prefix-len-hint
+ validators: []
+ spec: {}
+ description: Send prefix length hint to server
+ required: false
+ variants: []
+ description: Enable Prefix Delegation
+ required: false
+ description: Enable/Disable Prefix Delegation
+ required: false
+ variants: []
+ description: Configure Prefix Delegation Options
+ required: false
+ - name: v6-options
+ type: object
+ profiles:
+ - xpath:
+ - v6-options
+ validators: []
+ spec:
+ params:
+ - name: duid-type
+ type: enum
+ profiles:
+ - xpath:
+ - duid-type
+ validators:
+ - type: values
+ spec:
+ values:
+ - duid-type-llt
+ - duid-type-ll
+ spec:
+ default: duid-type-llt
+ values:
+ - value: duid-type-llt
+ - value: duid-type-ll
+ description: Select DUID-LLT/DUID-LL
+ required: false
+ - name: enable
+ type: object
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: 'no'
+ type: object
+ profiles:
+ - xpath:
+ - 'no'
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Disable IPv6 Address
+ required: false
+ - name: 'yes'
+ type: object
+ profiles:
+ - xpath:
+ - 'yes'
+ validators: []
+ spec:
+ params:
+ - name: non-temp-addr
+ type: bool
+ profiles:
+ - xpath:
+ - non-temp-addr
+ validators: []
+ spec: {}
+ description: Request Non-Temporary Address Type
+ required: false
+ - name: temp-addr
+ type: bool
+ profiles:
+ - xpath:
+ - temp-addr
+ validators: []
+ spec: {}
+ description: Request Temporary Address Type
+ required: false
+ variants: []
+ description: Enable IPv6 Address
+ required: false
+ description: Enable/Disable IPv6 Address
+ required: false
+ - name: rapid-commit
+ type: bool
+ profiles:
+ - xpath:
+ - rapid-commit
+ validators: []
+ spec: {}
+ description: Enable Rapid Commit
+ required: false
+ - name: support-srvr-reconfig
+ type: bool
+ profiles:
+ - xpath:
+ - support-srvr-reconfig
+ validators: []
+ spec: {}
+ description: Enable DHCPv6 Server Re-Configuration Support
+ required: false
+ variants: []
+ description: Configure DHCPv6 Options
+ required: false
+ variants: []
+ description: Configure DHCPv6 Client
+ required: false
+ - name: enabled
+ type: bool
+ profiles:
+ - xpath:
+ - enabled
+ validators: []
+ spec: {}
+ description: Enable IPv6 on the interface
+ required: false
+ - name: inherited
+ type: object
+ profiles:
+ - xpath:
+ - inherited
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec:
+ params:
+ - name: assign-addr
+ type: list
+ profiles:
+ - xpath:
+ - assign-addr
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: type
+ type: object
+ profiles:
+ - xpath:
+ - type
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: gua
+ type: object
+ profiles:
+ - xpath:
+ - gua
+ validators: []
+ spec:
+ params:
+ - name: enable-on-interface
+ type: bool
+ profiles:
+ - xpath:
+ - enable-on-interface
+ validators: []
+ spec: {}
+ description: Enable on Interface
+ required: false
+ - name: prefix-pool
+ type: string
+ profiles:
+ - xpath:
+ - prefix-pool
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Prefix-Pool Name
+ required: false
+ - name: pool-type
+ type: object
+ profiles:
+ - xpath:
+ - pool-type
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: dynamic
+ type: object
+ profiles:
+ - xpath:
+ - dynamic
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: Dynamically allocate Pool to member Interfaces
+ required: false
+ - name: dynamic-id
+ type: object
+ profiles:
+ - xpath:
+ - dynamic-id
+ validators: []
+ spec:
+ params:
+ - name: identifier
+ type: int64
+ profiles:
+ - xpath:
+ - identifier
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 4095
+ spec: {}
+ description: Range [0-4095] must be unqiue for
+ this prefix-pool
+ required: false
+ variants: []
+ description: Assign Id to selected delegate prefix
+ from the pool
+ required: false
+ description: Select Pool Allocation Method
+ required: false
+ - name: advertise
+ type: object
+ profiles:
+ - xpath:
+ - advertise
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable advertising this prefix in router
+ advertisements
+ required: false
+ - name: onlink-flag
+ type: bool
+ profiles:
+ - xpath:
+ - onlink-flag
+ validators: []
+ spec: {}
+ description: Set the On-Link Flag (L-bit) of the prefix
+ in Router Advertisement messages
+ required: false
+ - name: auto-config-flag
+ type: bool
+ profiles:
+ - xpath:
+ - auto-config-flag
+ validators: []
+ spec: {}
+ description: Set the Auto Address Configuration Flag
+ (A-bit) of the prefix in Router Advertisement messages
+ required: false
+ variants: []
+ description: Configure router advertisement prefix options
+ required: false
+ variants: []
+ description: Select GUA (Global Unique Address)from Pool
+ required: false
+ - name: ula
+ type: object
+ profiles:
+ - xpath:
+ - ula
+ validators: []
+ spec:
+ params:
+ - name: enable-on-interface
+ type: bool
+ profiles:
+ - xpath:
+ - enable-on-interface
+ validators: []
+ spec: {}
+ description: Configure this address on Interface
+ required: false
+ - name: address
+ type: string
+ profiles:
+ - xpath:
+ - address
+ validators: []
+ spec: {}
+ description: Configure ULA (Unique Local Address)
+ required: false
+ - name: prefix
+ type: bool
+ profiles:
+ - xpath:
+ - prefix
+ validators: []
+ spec: {}
+ description: Use this as prefix to form full address with
+ interface id/EUI-64
+ required: false
+ - name: anycast
+ type: bool
+ profiles:
+ - xpath:
+ - anycast
+ validators: []
+ spec: {}
+ description: Anycast Address
+ required: false
+ - name: advertise
+ type: object
+ profiles:
+ - xpath:
+ - advertise
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: enable advertising this prefix in router
+ advertisements
+ required: false
+ - name: valid-lifetime
+ type: string
+ profiles:
+ - xpath:
+ - valid-lifetime
+ validators: []
+ spec:
+ default: '2592000'
+ description: Valid Lifetime (in seconds) of the prefix
+ advertised in Router Advertisement messages
+ required: false
+ - name: preferred-lifetime
+ type: string
+ profiles:
+ - xpath:
+ - preferred-lifetime
+ validators: []
+ spec:
+ default: '604800'
+ description: Preferred Lifetime (in seconds) of the
+ prefix advertised in Router advertisement messages
+ required: false
+ - name: onlink-flag
+ type: bool
+ profiles:
+ - xpath:
+ - onlink-flag
+ validators: []
+ spec: {}
+ description: Set the On-Link Flag (L-bit) of the prefix
+ in Router Advertisement messages
+ required: false
+ - name: auto-config-flag
+ type: bool
+ profiles:
+ - xpath:
+ - auto-config-flag
+ validators: []
+ spec: {}
+ description: Set the Auto Address Configuration Flag
+ (A-bit) of the prefix in Router Advertisement messages
+ required: false
+ variants: []
+ description: Configure router advertisement prefix options
+ required: false
+ variants: []
+ description: Configure ULA (Unique Local Address)
+ required: false
+ description: Select Address Source Type
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable Inherited Interface
+ required: false
+ - name: neighbor-discovery
+ type: object
+ profiles:
+ - xpath:
+ - neighbor-discovery
+ validators: []
+ spec:
+ params:
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 10
+ spec:
+ default: 1
+ description: Number of consecutive neighbor solicitation messages
+ sent for duplicate address detection
+ required: false
+ - name: dns-server
+ type: object
+ profiles:
+ - xpath:
+ - dns-server
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: source
+ type: object
+ profiles:
+ - xpath:
+ - source
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params:
+ - name: prefix-pool
+ type: string
+ profiles:
+ - xpath:
+ - prefix-pool
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Prefix-Pool Name
+ required: false
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
+ type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
+ spec:
+ params:
+ - name: server
+ type: list
+ profiles:
+ - xpath:
+ - server
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) Lifetime in Seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually configure
+ required: false
+ variants: []
+ description: DNS Recursive Name Server
+ required: false
+ - name: dns-suffix
+ type: object
+ profiles:
+ - xpath:
+ - dns-suffix
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: source
+ type: object
+ profiles:
+ - xpath:
+ - source
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: dhcpv6
+ type: object
+ profiles:
+ - xpath:
+ - dhcpv6
+ validators: []
+ spec:
+ params:
+ - name: prefix-pool
+ type: string
+ profiles:
+ - xpath:
+ - prefix-pool
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Prefix-Pool Name
+ required: false
+ variants: []
+ description: Source from DHCPv6 Server
+ required: false
+ - name: manual
+ type: object
+ profiles:
+ - xpath:
+ - manual
+ validators: []
+ spec:
+ params:
+ - name: suffix
+ type: list
+ profiles:
+ - xpath:
+ - suffix
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: Configure manually
+ required: false
+ description: Either source from DHCPv6 Server or manually configure
+ required: false
+ variants: []
+ description: Domain Search List
+ required: false
+ - name: enable-dad
+ type: bool
+ profiles:
+ - xpath:
+ - enable-dad
+ validators: []
+ spec: {}
+ description: Enable Duplicate Address Detection (DAD)
+ required: false
+ - name: enable-ndp-monitor
+ type: bool
+ profiles:
+ - xpath:
+ - enable-ndp-monitor
+ validators: []
+ spec: {}
+ description: Enable NDP Monitoring
+ required: false
+ - name: neighbor
+ type: list
+ profiles:
+ - xpath:
+ - neighbor
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: ns-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ns-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 3600
+ spec:
+ default: 1
+ description: Interval (in seconds) between consecutive neighbor solicitation
+ messages
+ required: false
+ - name: reachable-time
+ type: int64
+ profiles:
+ - xpath:
+ - reachable-time
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 36000
+ spec:
+ default: 30
+ description: Time (in seconds) that the Reachable status for a neighbor
+ can be maintained
+ required: false
+ - name: router-advertisement
+ type: object
+ profiles:
+ - xpath:
+ - router-advertisement
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: enable-consistency-check
+ type: bool
+ profiles:
+ - xpath:
+ - enable-consistency-check
+ validators: []
+ spec: {}
+ description: check consistency of RA messages from other routers.
+ required: false
+ - name: hop-limit
+ type: string
+ profiles:
+ - xpath:
+ - hop-limit
+ validators: []
+ spec:
+ default: '64'
+ description: Current Hop Limit advertised in Router Advertisement
+ messages
+ required: false
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 9000
+ spec:
+ default: 1800
+ description: Router Lifetime (in seconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: link-mtu
+ type: string
+ profiles:
+ - xpath:
+ - link-mtu
+ validators: []
+ spec:
+ default: unspecified
+ description: value of MTU option in Router Advertisement messages,
+ upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
+ required: false
+ - name: managed-flag
+ type: bool
+ profiles:
+ - xpath:
+ - managed-flag
+ validators: []
+ spec: {}
+ description: Set the Managed Configuration Flag (M-bit) in Router
+ Advertisement messages
+ required: false
+ - name: max-interval
+ type: int64
+ profiles:
+ - xpath:
+ - max-interval
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 1800
+ spec:
+ default: 600
+ description: Maximum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: min-interval
+ type: int64
+ profiles:
+ - xpath:
+ - min-interval
+ validators:
+ - type: length
+ spec:
+ min: 3
+ max: 1350
+ spec:
+ default: 200
+ description: Minimum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: other-flag
+ type: bool
+ profiles:
+ - xpath:
+ - other-flag
+ validators: []
+ spec: {}
+ description: Set the Other Stateful Configuration Flag (O-bit)
+ in Router Advertisement messages
+ required: false
+ - name: reachable-time
+ type: string
+ profiles:
+ - xpath:
+ - reachable-time
+ validators: []
+ spec:
+ default: unspecified
+ description: Reachable Time (in milliseconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: retransmission-timer
+ type: string
+ profiles:
+ - xpath:
+ - retransmission-timer
+ validators: []
+ spec:
+ default: unspecified
+ description: Retransmission Timer (in milliseconds) advertised
+ in Router Advertisement messages
+ required: false
+ - name: router-preference
+ type: enum
+ profiles:
+ - xpath:
+ - router-preference
+ validators:
+ - type: values
+ spec:
+ values:
+ - High
+ - Medium
+ - Low
+ spec:
+ default: Medium
+ values:
+ - value: High
+ - value: Medium
+ - value: Low
+ description: ''
+ required: false
+ variants: []
+ description: Router Advertisement configuration
+ required: false
+ variants: []
+ description: Neighbor Discovery configuration
+ required: false
+ variants: []
+ description: Configure to inherit properties from another interface
+ required: false
+ - name: interface-id
+ type: string
+ profiles:
+ - xpath:
+ - interface-id
+ validators: []
+ spec:
+ default: EUI-64
+ description: ''
+ required: false
+ - name: neighbor-discovery
+ type: object
+ profiles:
+ - xpath:
+ - neighbor-discovery
+ validators: []
+ spec:
+ params:
+ - name: dad-attempts
+ type: int64
+ profiles:
+ - xpath:
+ - dad-attempts
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 10
+ spec:
+ default: 1
+ description: number of consecutive neighbor solicitation messages sent
+ for duplicate address detection
+ required: false
+ - name: enable-dad
+ type: bool
+ profiles:
+ - xpath:
+ - enable-dad
+ validators: []
+ spec: {}
+ description: enable duplicate address detection
+ required: false
+ - name: enable-ndp-monitor
+ type: bool
+ profiles:
+ - xpath:
+ - enable-ndp-monitor
+ validators: []
+ spec: {}
+ description: enable ndp monitoring
+ required: false
+ - name: neighbor
+ type: list
+ profiles:
+ - xpath:
+ - neighbor
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: hw-address
+ type: string
+ profiles:
+ - xpath:
+ - hw-address
+ validators: []
+ spec: {}
+ description: MAC address (format xx:xx:xx:xx:xx:xx)
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: ns-interval
+ type: int64
+ profiles:
+ - xpath:
+ - ns-interval
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 3600
+ spec:
+ default: 1
+ description: interval (in seconds) between consecutive neighbor solicitation
+ messages
+ required: false
+ - name: reachable-time
+ type: int64
+ profiles:
+ - xpath:
+ - reachable-time
+ validators:
+ - type: length
+ spec:
+ min: 10
+ max: 36000
+ spec:
+ default: 30
+ description: time (in seconds) that the Reachable status for a neighbor
+ can be maintained
+ required: false
+ - name: router-advertisement
+ type: object
+ profiles:
+ - xpath:
+ - router-advertisement
+ validators: []
+ spec:
+ params:
+ - name: dns-support
+ type: object
+ profiles:
+ - xpath:
+ - dns-support
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: server
+ type: list
+ profiles:
+ - xpath:
+ - server
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: suffix
+ type: list
+ profiles:
+ - xpath:
+ - suffix
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 3600
+ spec:
+ default: 1200
+ description: (4-3600) lifetime in seconds
+ required: false
+ variants: []
+ description: ''
+ required: false
+ variants: []
+ description: DNS configuration support
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: enable-consistency-check
+ type: bool
+ profiles:
+ - xpath:
+ - enable-consistency-check
+ validators: []
+ spec: {}
+ description: check consistency of RA messages from other routers.
+ required: false
+ - name: hop-limit
+ type: string
+ profiles:
+ - xpath:
+ - hop-limit
+ validators: []
+ spec:
+ default: '64'
+ description: Current Hop Limit advertised in Router Advertisement
+ messages
+ required: false
+ - name: lifetime
+ type: int64
+ profiles:
+ - xpath:
+ - lifetime
+ validators:
+ - type: length
+ spec:
+ min: 0
+ max: 9000
+ spec:
+ default: 1800
+ description: Router Lifetime (in seconds) advertised in Router Advertisement
+ messages
+ required: false
+ - name: link-mtu
+ type: string
+ profiles:
+ - xpath:
+ - link-mtu
+ validators: []
+ spec:
+ default: unspecified
+ description: value of MTU option in Router Advertisement messages,
+ upto 9216 in Jumbo-Frame mode, up to 1500 otherwise
+ required: false
+ - name: managed-flag
+ type: bool
+ profiles:
+ - xpath:
+ - managed-flag
+ validators: []
+ spec: {}
+ description: Set the Managed Configuration Flag (M-bit) in Router
+ Advertisement messages
+ required: false
+ - name: max-interval
+ type: int64
+ profiles:
+ - xpath:
+ - max-interval
+ validators:
+ - type: length
+ spec:
+ min: 4
+ max: 1800
+ spec:
+ default: 600
+ description: Maximum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: min-interval
+ type: int64
+ profiles:
+ - xpath:
+ - min-interval
+ validators:
+ - type: length
+ spec:
+ min: 3
+ max: 1350
+ spec:
+ default: 200
+ description: Minimum interval (seconds) between consecutive unsolicited
+ Router Advertisement messages
+ required: false
+ - name: other-flag
+ type: bool
+ profiles:
+ - xpath:
+ - other-flag
+ validators: []
+ spec: {}
+ description: Set the Other Stateful Configuration Flag (O-bit) in
+ Router Advertisement messages
+ required: false
+ - name: reachable-time
+ type: string
+ profiles:
+ - xpath:
+ - reachable-time
+ validators: []
+ spec:
+ default: unspecified
+ description: Reachable Time (in milliseconds) advertised in Router
+ Advertisement messages
+ required: false
+ - name: retransmission-timer
+ type: string
+ profiles:
+ - xpath:
+ - retransmission-timer
+ validators: []
+ spec:
+ default: unspecified
+ description: Retransmission Timer (in milliseconds) advertised in
+ Router Advertisement messages
+ required: false
+ - name: router-preference
+ type: enum
+ profiles:
+ - xpath:
+ - router-preference
+ validators:
+ - type: values
+ spec:
+ values:
+ - High
+ - Medium
+ - Low
+ spec:
+ default: Medium
+ values:
+ - value: High
+ - value: Medium
+ - value: Low
+ description: ''
+ required: false
+ variants: []
+ description: Router advertisement configuration
+ required: false
+ variants: []
+ description: Neighbor Discovery configuration
+ required: false
+ variants: []
+ description: Interface IPv6 configuration
+ required: false
+ - name: mtu
+ type: int64
+ profiles:
+ - xpath:
+ - mtu
+ validators:
+ - type: length
+ spec:
+ min: 576
+ max: 9216
+ spec: {}
+ description: Maximum Transfer Unit, up to 9216 in Jumbo-Frame mode, up to 1500
+ otherwise
+ required: false
+ - name: ndp-proxy
+ type: object
+ profiles:
+ - xpath:
+ - ndp-proxy
+ validators: []
+ spec:
+ params:
+ - name: address
+ type: list
+ profiles:
+ - xpath:
+ - address
+ - entry
+ type: entry
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: negate
+ type: bool
+ profiles:
+ - xpath:
+ - negate
+ validators: []
+ spec: {}
+ description: put the prefix or address on a block list
+ required: false
+ variants: []
+ description: ''
+ required: false
+ - name: enabled
+ type: bool
+ profiles:
+ - xpath:
+ - enabled
+ validators: []
+ spec: {}
+ description: Enable proxy NDP on the interface
+ required: false
+ variants: []
+ description: proxy-ndp configuration
+ required: false
+ - name: netflow-profile
+ type: string
+ profiles:
+ - xpath:
+ - netflow-profile
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: Netflow Server Profile
+ required: false
+ - name: pppoe
+ type: object
+ profiles:
+ - xpath:
+ - pppoe
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec:
+ params:
+ - name: access-concentrator
+ type: string
+ profiles:
+ - xpath:
+ - access-concentrator
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 255
+ spec: {}
+ description: desired access concentrator. The valid characters are [a-zA-Z0-9._~!@#$%^*(){},:?/+=\-]
+ required: false
+ - name: authentication
+ type: enum
+ profiles:
+ - xpath:
+ - authentication
+ validators:
+ - type: values
+ spec:
+ values:
+ - CHAP
+ - PAP
+ - auto
+ spec:
+ values:
+ - value: CHAP
+ - value: PAP
+ - value: auto
+ description: authentication protocol
+ required: false
+ - name: create-default-route
+ type: bool
+ profiles:
+ - xpath:
+ - create-default-route
+ validators: []
+ spec: {}
+ description: automatically create default route pointing to peer
+ required: false
+ - name: default-route-metric
+ type: int64
+ profiles:
+ - xpath:
+ - default-route-metric
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 65535
+ spec:
+ default: 10
+ description: metric of the default route created
+ required: false
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: passive
+ type: object
+ profiles:
+ - xpath:
+ - passive
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ variants: []
+ description: devices awaits PPP request from peer
+ required: false
+ - name: password
+ type: string
+ profiles:
+ - xpath:
+ - password
+ validators:
+ - type: length
+ spec:
+ max: 255
+ spec: {}
+ description: password for ppp autentication
+ required: false
+ codegen_overrides:
+ terraform:
+ sensitive: true
+ hashing:
+ type: solo
+ - name: service
+ type: string
+ profiles:
+ - xpath:
+ - service
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 255
+ spec: {}
+ description: desired service. The valid characters are [a-zA-Z0-9._~!@#$%^*(){},:?/+=\-]
+ required: false
+ - name: static-address
+ type: object
+ profiles:
+ - xpath:
+ - static-address
+ validators: []
+ spec:
+ params:
+ - name: ip
+ type: string
+ profiles:
+ - xpath:
+ - ip
+ validators:
+ - type: length
+ spec:
+ max: 63
+ spec: {}
+ description: static ip address
+ required: false
+ variants: []
+ description: use static interface address
+ required: false
+ - name: username
+ type: string
+ profiles:
+ - xpath:
+ - username
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 255
+ spec: {}
+ description: username for ppp authentication. The valid characters are [a-zA-Z0-9._~!@#$%^*(){},:?/+=\-]
+ required: false
+ variants: []
+ description: pppoe configuration
+ required: false
+ - name: sdwan-link-settings
+ type: object
+ profiles:
+ - xpath:
+ - sdwan-link-settings
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable sdwan on this ethernet interface
+ required: false
+ - name: sdwan-interface-profile
+ type: string
+ profiles:
+ - xpath:
+ - sdwan-interface-profile
+ validators:
+ - type: length
+ spec:
+ max: 31
+ spec: {}
+ description: Sdwan link characteristics
+ required: false
+ - name: upstream-nat
+ type: object
+ profiles:
+ - xpath:
+ - upstream-nat
+ validators: []
+ spec:
+ params:
+ - name: enable
+ type: bool
+ profiles:
+ - xpath:
+ - enable
+ validators: []
+ spec: {}
+ description: Enable upstream NAT IP config
+ required: false
+ variants:
+ - name: ddns
+ type: object
+ profiles:
+ - xpath:
+ - ddns
+ validators: []
+ spec:
+ params: []
+ variants: []
+ description: DDNS derives upstream NAT IP
+ required: false
+ variant_group_id: 0
+ - name: static-ip
+ type: object
+ profiles:
+ - xpath:
+ - static-ip
+ validators: []
+ spec:
+ params: []
+ variants:
+ - name: fqdn
+ type: string
+ profiles:
+ - xpath:
+ - fqdn
+ validators:
+ - type: length
+ spec:
+ max: 255
+ spec: {}
+ description: Upstream NAT address FQDN name configuration
+ required: false
+ variant_group_id: 0
+ - name: ip-address
+ type: string
+ profiles:
+ - xpath:
+ - ip-address
+ validators: []
+ spec: {}
+ description: Upstream NAT IP address
+ required: false
+ variant_group_id: 0
+ description: Upstream NAT IP address
+ required: false
+ variant_group_id: 0
+ description: Upstream NAT IP config
+ required: false
+ variants: []
+ description: Sdwan related settings
+ required: false
+ - name: tag
+ type: int64
+ profiles:
+ - xpath:
+ - tag
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 4094
+ spec: {}
+ description: 802.1q VLAN tag
+ required: false
+ variants: []
diff --git a/specs/network/tunnels/ipsec.yaml b/specs/network/tunnels/ipsec.yaml
index b6935d37..0f614943 100644
--- a/specs/network/tunnels/ipsec.yaml
+++ b/specs/network/tunnels/ipsec.yaml
@@ -16,10 +16,12 @@ go_sdk_config:
- network
- tunnel
- ipsec
-xpath_suffix:
-- network
-- tunnel
-- ipsec
+panos_xpath:
+ path:
+ - network
+ - tunnel
+ - ipsec
+ vars: []
locations:
- name: template
xpath:
@@ -185,6 +187,26 @@ spec:
spec: {}
description: allow GRE over IPSec
required: false
+ - name: ipsec-mode
+ type: enum
+ profiles:
+ - xpath:
+ - ipsec-mode
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators:
+ - type: values
+ spec:
+ values:
+ - tunnel
+ - transport
+ spec:
+ default: tunnel
+ values:
+ - value: tunnel
+ - value: transport
+ description: ''
+ required: false
- name: ipv6
type: bool
profiles:
@@ -250,26 +272,6 @@ spec:
variants: []
description: Monitor tunnel status
required: false
- - name: ipsec-mode
- type: enum
- profiles:
- - xpath:
- - ipsec-mode
- min_version: 11.0.2
- max_version: 11.0.3
- validators:
- - type: values
- spec:
- values:
- - tunnel
- - transport
- spec:
- default: tunnel
- values:
- - value: tunnel
- - value: transport
- description: ''
- required: false
variants:
- name: auto-key
type: object
@@ -605,6 +607,7 @@ spec:
variants: []
description: IKE VPN options
required: false
+ variant_group_id: 0
- name: global-protect-satellite
type: object
profiles:
@@ -702,6 +705,7 @@ spec:
variants: []
description: Floating IP address in HA Active-Active configuration
required: false
+ variant_group_id: 0
- name: ip
type: object
profiles:
@@ -732,6 +736,7 @@ spec:
variants: []
description: specify exact IP address if interface has multiple addresses
required: false
+ variant_group_id: 0
description: Satellite outgoing interface configuration
required: false
- name: portal-address
@@ -782,6 +787,7 @@ spec:
variants: []
description: Satellite side of Global Protect Satellite tunnel
required: false
+ variant_group_id: 0
- name: manual-key
type: object
profiles:
@@ -817,6 +823,7 @@ spec:
spec: {}
description: Floating IP address in HA Active-Active configuration
required: false
+ variant_group_id: 0
- name: ip
type: string
profiles:
@@ -829,6 +836,7 @@ spec:
spec: {}
description: specify exact IP address if interface has multiple addresses
required: false
+ variant_group_id: 0
description: Tunnel local IP configuration
required: false
- name: local-spi
@@ -902,6 +910,7 @@ spec:
variants: []
description: key is 128 bit
required: false
+ variant_group_id: 0
- name: sha1
type: object
profiles:
@@ -925,6 +934,7 @@ spec:
variants: []
description: key is 160 bit
required: false
+ variant_group_id: 0
- name: sha256
type: object
profiles:
@@ -948,6 +958,7 @@ spec:
variants: []
description: key is 256 bit
required: false
+ variant_group_id: 0
- name: sha384
type: object
profiles:
@@ -971,6 +982,7 @@ spec:
variants: []
description: key is 384 bit
required: false
+ variant_group_id: 0
- name: sha512
type: object
profiles:
@@ -994,8 +1006,10 @@ spec:
variants: []
description: key is 512 bit
required: false
+ variant_group_id: 0
description: AH options
required: false
+ variant_group_id: 0
- name: esp
type: object
profiles:
@@ -1036,6 +1050,7 @@ spec:
variants: []
description: key is 128 bit
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -1047,6 +1062,7 @@ spec:
variants: []
description: no authentication
required: false
+ variant_group_id: 0
- name: sha1
type: object
profiles:
@@ -1070,6 +1086,7 @@ spec:
variants: []
description: key is 160 bit
required: false
+ variant_group_id: 0
- name: sha256
type: object
profiles:
@@ -1093,6 +1110,7 @@ spec:
variants: []
description: key is 256 bit
required: false
+ variant_group_id: 0
- name: sha384
type: object
profiles:
@@ -1116,6 +1134,7 @@ spec:
variants: []
description: key is 384 bit
required: false
+ variant_group_id: 0
- name: sha512
type: object
profiles:
@@ -1139,6 +1158,7 @@ spec:
variants: []
description: key is 512 bit
required: false
+ variant_group_id: 0
description: authentication algorithm
required: false
- name: encryption
@@ -1194,5 +1214,7 @@ spec:
variants: []
description: ESP options
required: false
+ variant_group_id: 0
description: Manual-key options
required: false
+ variant_group_id: 0
diff --git a/specs/network/virtual-router.yaml b/specs/network/virtual-router.yaml
index b07a567b..a55ae18b 100644
--- a/specs/network/virtual-router.yaml
+++ b/specs/network/virtual-router.yaml
@@ -15,9 +15,11 @@ go_sdk_config:
package:
- network
- virtual_router
-xpath_suffix:
-- network
-- virtual-router
+panos_xpath:
+ path:
+ - network
+ - virtual-router
+ vars: []
locations:
- name: ngfw
xpath:
@@ -283,6 +285,7 @@ spec:
variants: []
description: Re-balance load on path add/delete
required: false
+ variant_group_id: 0
- name: ip-hash
type: object
profiles:
@@ -326,6 +329,7 @@ spec:
variants: []
description: Hash based on IP addresses and optionally port numbers
required: false
+ variant_group_id: 0
- name: ip-modulo
type: object
profiles:
@@ -337,6 +341,7 @@ spec:
variants: []
description: IP addresses modulo number of path
required: false
+ variant_group_id: 0
- name: weighted-round-robin
type: object
profiles:
@@ -379,6 +384,7 @@ spec:
variants: []
description: Weighted round robin
required: false
+ variant_group_id: 0
description: load balancing algorithm
required: false
- name: enable
@@ -994,6 +1000,7 @@ spec:
variants: []
description: Configure device to act as candidate RP
required: false
+ variant_group_id: 0
- name: static-rp
type: object
profiles:
@@ -1051,6 +1058,7 @@ spec:
variants: []
description: Configure device to act as a static RP
required: false
+ variant_group_id: 0
description: Local Rendezvous Point configuration
required: false
variants: []
@@ -1730,6 +1738,7 @@ spec:
spec: {}
description: peer address configuration
required: false
+ variant_group_id: 0
- name: fqdn
type: string
profiles:
@@ -1742,6 +1751,7 @@ spec:
spec: {}
description: bgp peer FQDN address object configuration
required: false
+ variant_group_id: 0
description: peer address configuration
required: false
- name: connection-options
@@ -2114,6 +2124,7 @@ spec:
variants: []
description: no change on AS path
required: false
+ variant_group_id: 0
- name: prepend
type: int64
profiles:
@@ -2129,6 +2140,7 @@ spec:
description: prepend local AS for specified number
of times
required: false
+ variant_group_id: 0
description: AS path update options
required: false
- name: community
@@ -2151,6 +2163,7 @@ spec:
variants: []
description: no change on communities
required: false
+ variant_group_id: 0
- name: remove-all
type: object
profiles:
@@ -2162,6 +2175,7 @@ spec:
variants: []
description: remove all communities
required: false
+ variant_group_id: 0
- name: remove-regex
type: string
profiles:
@@ -2175,6 +2189,7 @@ spec:
description: remove specified coummnity match
regular expression
required: false
+ variant_group_id: 0
- name: append
type: list
profiles:
@@ -2188,6 +2203,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: overwrite
type: list
profiles:
@@ -2201,6 +2217,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: community update options
required: false
- name: extended-community
@@ -2223,6 +2240,7 @@ spec:
variants: []
description: no change on communities
required: false
+ variant_group_id: 0
- name: remove-all
type: object
profiles:
@@ -2234,6 +2252,7 @@ spec:
variants: []
description: remove all communities
required: false
+ variant_group_id: 0
- name: remove-regex
type: string
profiles:
@@ -2247,6 +2266,7 @@ spec:
description: remove specified coummnity match
regular expression
required: false
+ variant_group_id: 0
- name: append
type: list
profiles:
@@ -2260,6 +2280,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: overwrite
type: list
profiles:
@@ -2273,6 +2294,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: extended community update options
required: false
variants: []
@@ -2415,6 +2437,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: AS-path to match
required: false
- name: community
@@ -2438,6 +2461,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
- name: extended-community
@@ -2461,6 +2485,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
variants: []
@@ -2606,6 +2631,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: AS-path to match
required: false
- name: community
@@ -2629,6 +2655,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
- name: extended-community
@@ -2652,6 +2679,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
variants: []
@@ -2838,6 +2866,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: AS-path to match
required: false
- name: community
@@ -2861,6 +2890,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
- name: extended-community
@@ -2884,6 +2914,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
variants: []
@@ -3020,6 +3051,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: AS-path to match
required: false
- name: community
@@ -3043,6 +3075,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
- name: extended-community
@@ -3066,6 +3099,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
variants: []
@@ -3238,6 +3272,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: AS-path to match
required: false
- name: community
@@ -3261,6 +3296,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
- name: extended-community
@@ -3284,6 +3320,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
variants: []
@@ -3309,6 +3346,7 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
- name: allow
type: object
profiles:
@@ -3413,6 +3451,7 @@ spec:
variants: []
description: no change on AS path
required: false
+ variant_group_id: 0
- name: remove
type: object
profiles:
@@ -3424,6 +3463,7 @@ spec:
variants: []
description: remove matched AS path(s)
required: false
+ variant_group_id: 0
- name: prepend
type: int64
profiles:
@@ -3439,6 +3479,7 @@ spec:
description: prepend local AS for specified
number of times
required: false
+ variant_group_id: 0
- name: remove-and-prepend
type: int64
profiles:
@@ -3455,6 +3496,7 @@ spec:
and prepend local AS for specified number
of times
required: false
+ variant_group_id: 0
description: AS path update options
required: false
- name: community
@@ -3477,6 +3519,7 @@ spec:
variants: []
description: no change on communities
required: false
+ variant_group_id: 0
- name: remove-all
type: object
profiles:
@@ -3488,6 +3531,7 @@ spec:
variants: []
description: remove all communities
required: false
+ variant_group_id: 0
- name: remove-regex
type: string
profiles:
@@ -3501,6 +3545,7 @@ spec:
description: remove specified coummnity
match regular expression
required: false
+ variant_group_id: 0
- name: append
type: list
profiles:
@@ -3514,6 +3559,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: overwrite
type: list
profiles:
@@ -3527,6 +3573,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: community update options
required: false
- name: extended-community
@@ -3549,6 +3596,7 @@ spec:
variants: []
description: no change on communities
required: false
+ variant_group_id: 0
- name: remove-all
type: object
profiles:
@@ -3560,6 +3608,7 @@ spec:
variants: []
description: remove all communities
required: false
+ variant_group_id: 0
- name: remove-regex
type: string
profiles:
@@ -3573,6 +3622,7 @@ spec:
description: remove specified coummnity
match regular expression
required: false
+ variant_group_id: 0
- name: append
type: list
profiles:
@@ -3586,6 +3636,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: overwrite
type: list
profiles:
@@ -3599,6 +3650,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: extended community update options
required: false
variants: []
@@ -3607,6 +3659,7 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
description: rule action
required: false
variants: []
@@ -3773,6 +3826,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: AS-path to match
required: false
- name: community
@@ -3796,6 +3850,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
- name: extended-community
@@ -3819,6 +3874,7 @@ spec:
spec: {}
description: AS-path regular expression
required: false
+ variant_group_id: 0
description: community to match
required: false
variants: []
@@ -3844,6 +3900,7 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
- name: allow
type: object
profiles:
@@ -3970,6 +4027,7 @@ spec:
variants: []
description: no change on AS path
required: false
+ variant_group_id: 0
- name: remove
type: object
profiles:
@@ -3981,6 +4039,7 @@ spec:
variants: []
description: remove matched AS path(s)
required: false
+ variant_group_id: 0
description: AS path update options
required: false
- name: community
@@ -4003,6 +4062,7 @@ spec:
variants: []
description: no change on communities
required: false
+ variant_group_id: 0
- name: remove-all
type: object
profiles:
@@ -4014,6 +4074,7 @@ spec:
variants: []
description: remove all communities
required: false
+ variant_group_id: 0
- name: remove-regex
type: string
profiles:
@@ -4027,6 +4088,7 @@ spec:
description: remove specified coummnity
match regular expression
required: false
+ variant_group_id: 0
- name: append
type: list
profiles:
@@ -4040,6 +4102,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: overwrite
type: list
profiles:
@@ -4053,6 +4116,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: community update options
required: false
- name: extended-community
@@ -4075,6 +4139,7 @@ spec:
variants: []
description: no change on communities
required: false
+ variant_group_id: 0
- name: remove-all
type: object
profiles:
@@ -4086,6 +4151,7 @@ spec:
variants: []
description: remove all communities
required: false
+ variant_group_id: 0
- name: remove-regex
type: string
profiles:
@@ -4099,6 +4165,7 @@ spec:
description: remove specified coummnity
match regular expression
required: false
+ variant_group_id: 0
- name: append
type: list
profiles:
@@ -4112,6 +4179,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: overwrite
type: list
profiles:
@@ -4125,6 +4193,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: extended community update options
required: false
variants: []
@@ -4133,6 +4202,7 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
description: rule action
required: false
variants: []
@@ -4732,6 +4802,7 @@ spec:
variants: []
description: do summarization and advertise
required: false
+ variant_group_id: 0
- name: suppress
type: object
profiles:
@@ -4744,6 +4815,7 @@ spec:
description: suppress summarization to be sent,
make this subnet hidden from other areas
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -4777,6 +4849,7 @@ spec:
variants: []
description: do summarization and advertise
required: false
+ variant_group_id: 0
- name: suppress
type: object
profiles:
@@ -4789,6 +4862,7 @@ spec:
description: suppress summarization to be sent, make this
subnet hidden from other areas
required: false
+ variant_group_id: 0
description: ''
required: false
- name: interface
@@ -5182,6 +5256,7 @@ spec:
spec: {}
description: Simple password authentication
required: false
+ variant_group_id: 0
- name: md5
type: list
profiles:
@@ -5220,6 +5295,7 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
description: ''
required: false
- name: enable
@@ -5691,6 +5767,7 @@ spec:
variants: []
description: do summarization and advertise
required: false
+ variant_group_id: 0
- name: suppress
type: object
profiles:
@@ -5703,6 +5780,7 @@ spec:
description: suppress summarization to be sent,
make this subnet hidden from other areas
required: false
+ variant_group_id: 0
description: ''
required: false
variants: []
@@ -5736,6 +5814,7 @@ spec:
variants: []
description: do summarization and advertise
required: false
+ variant_group_id: 0
- name: suppress
type: object
profiles:
@@ -5748,6 +5827,7 @@ spec:
description: suppress summarization to be sent, make this
subnet hidden from other areas
required: false
+ variant_group_id: 0
description: ''
required: false
- name: interface
@@ -6208,6 +6288,7 @@ spec:
variants: []
description: key is 128 bit
required: false
+ variant_group_id: 0
- name: sha1
type: object
profiles:
@@ -6232,6 +6313,7 @@ spec:
variants: []
description: key is 160 bit
required: false
+ variant_group_id: 0
- name: sha256
type: object
profiles:
@@ -6256,6 +6338,7 @@ spec:
variants: []
description: key is 256 bit
required: false
+ variant_group_id: 0
- name: sha384
type: object
profiles:
@@ -6280,6 +6363,7 @@ spec:
variants: []
description: key is 384 bit
required: false
+ variant_group_id: 0
- name: sha512
type: object
profiles:
@@ -6304,6 +6388,7 @@ spec:
variants: []
description: key is 512 bit
required: false
+ variant_group_id: 0
- name: none
type: object
profiles:
@@ -6315,6 +6400,7 @@ spec:
variants: []
description: no authentication
required: false
+ variant_group_id: 0
description: authentication algorithm
required: false
- name: encryption
@@ -6368,6 +6454,7 @@ spec:
variants: []
description: ESP options
required: false
+ variant_group_id: 0
- name: ah
type: object
profiles:
@@ -6401,6 +6488,7 @@ spec:
variants: []
description: key is 128 bit
required: false
+ variant_group_id: 0
- name: sha1
type: object
profiles:
@@ -6425,6 +6513,7 @@ spec:
variants: []
description: key is 160 bit
required: false
+ variant_group_id: 0
- name: sha256
type: object
profiles:
@@ -6449,6 +6538,7 @@ spec:
variants: []
description: key is 256 bit
required: false
+ variant_group_id: 0
- name: sha384
type: object
profiles:
@@ -6473,6 +6563,7 @@ spec:
variants: []
description: key is 384 bit
required: false
+ variant_group_id: 0
- name: sha512
type: object
profiles:
@@ -6497,8 +6588,10 @@ spec:
variants: []
description: key is 512 bit
required: false
+ variant_group_id: 0
description: AH options
required: false
+ variant_group_id: 0
description: ''
required: false
- name: disable-transit-traffic
@@ -7222,6 +7315,7 @@ spec:
spec: {}
description: Simple password authentication
required: false
+ variant_group_id: 0
- name: md5
type: list
profiles:
@@ -7260,6 +7354,7 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
description: ''
required: false
- name: enable
@@ -7696,6 +7791,7 @@ spec:
variants: []
description: Install route into unicast routing table
required: false
+ variant_group_id: 0
- name: multicast
type: object
profiles:
@@ -7708,6 +7804,7 @@ spec:
description: Install route into multicast routing table, this
will create multicast routing table if not exists
required: false
+ variant_group_id: 0
- name: both
type: object
profiles:
@@ -7720,6 +7817,7 @@ spec:
description: Install route into both unicast and multicast
routing table
required: false
+ variant_group_id: 0
- name: no-install
type: object
profiles:
@@ -7731,6 +7829,7 @@ spec:
variants: []
description: Do not install route into forwarding table
required: false
+ variant_group_id: 0
description: target routing table to install the route
required: false
- name: bfd
@@ -8028,6 +8127,7 @@ spec:
variants: []
description: Install route into unicast routing table
required: false
+ variant_group_id: 0
- name: no-install
type: object
profiles:
@@ -8039,6 +8139,7 @@ spec:
variants: []
description: Do not install route into forwarding table
required: false
+ variant_group_id: 0
description: target routing table to install the route
required: false
- name: bfd
diff --git a/specs/network/zone.yaml b/specs/network/zone.yaml
index 17130f8d..c8c85b9b 100644
--- a/specs/network/zone.yaml
+++ b/specs/network/zone.yaml
@@ -15,8 +15,10 @@ go_sdk_config:
package:
- network
- zone
-xpath_suffix:
-- zone
+panos_xpath:
+ path:
+ - zone
+ vars: []
locations:
- name: vsys
xpath:
@@ -47,7 +49,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
@@ -225,15 +226,6 @@ spec:
spec: {}
description: Log setting for forwarding scan logs
required: false
- - name: zone-protection-profile
- type: string
- profiles:
- - xpath:
- - zone-protection-profile
- validators: []
- spec: {}
- description: Zone protection profile
- required: false
- name: net-inspection
type: bool
profiles:
@@ -245,6 +237,15 @@ spec:
spec: {}
description: ''
required: false
+ - name: zone-protection-profile
+ type: string
+ profiles:
+ - xpath:
+ - zone-protection-profile
+ validators: []
+ spec: {}
+ description: Zone protection profile
+ required: false
variants:
- name: external
type: list
@@ -259,6 +260,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: layer2
type: list
profiles:
@@ -272,6 +274,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: layer3
type: list
profiles:
@@ -285,6 +288,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: tap
type: list
profiles:
@@ -298,6 +302,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
- name: tunnel
type: object
profiles:
@@ -309,6 +314,7 @@ spec:
variants: []
description: Tunnel inspection zone
required: false
+ variant_group_id: 0
- name: virtual-wire
type: list
profiles:
@@ -322,6 +328,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: Zone network configuration
required: false
- name: user-acl
diff --git a/specs/objects/address-group.yaml b/specs/objects/address-group.yaml
index 66a1d034..9d69e4e8 100644
--- a/specs/objects/address-group.yaml
+++ b/specs/objects/address-group.yaml
@@ -16,8 +16,10 @@ go_sdk_config:
- objects
- address
- group
-xpath_suffix:
-- address-group
+panos_xpath:
+ path:
+ - address-group
+ vars: []
locations:
- name: shared
xpath:
@@ -61,7 +63,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
@@ -169,6 +170,7 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
- name: static
type: list
profiles:
@@ -182,3 +184,4 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
diff --git a/specs/objects/address.yaml b/specs/objects/address.yaml
index 12eff43c..91c29571 100644
--- a/specs/objects/address.yaml
+++ b/specs/objects/address.yaml
@@ -16,8 +16,10 @@ go_sdk_config:
package:
- objects
- address
-xpath_suffix:
-- address
+panos_xpath:
+ path:
+ - address
+ vars: []
locations:
- name: shared
xpath:
@@ -61,7 +63,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
@@ -164,6 +165,7 @@ spec:
spec: {}
description: The FQDN value.
required: false
+ variant_group_id: 0
- name: ip-netmask
type: string
profiles:
@@ -173,6 +175,7 @@ spec:
spec: {}
description: The IP netmask value.
required: false
+ variant_group_id: 0
- name: ip-range
type: string
profiles:
@@ -182,6 +185,7 @@ spec:
spec: {}
description: The IP range value.
required: false
+ variant_group_id: 0
- name: ip-wildcard
type: string
profiles:
@@ -191,3 +195,4 @@ spec:
spec: {}
description: The IP wildcard value.
required: false
+ variant_group_id: 0
diff --git a/specs/objects/administrative-tag.yaml b/specs/objects/administrative-tag.yaml
index 4f3245dd..7231dc72 100644
--- a/specs/objects/administrative-tag.yaml
+++ b/specs/objects/administrative-tag.yaml
@@ -15,8 +15,10 @@ go_sdk_config:
package:
- objects
- admintag
-xpath_suffix:
-- tag
+panos_xpath:
+ path:
+ - tag
+ vars: []
locations:
- name: shared
xpath:
@@ -60,7 +62,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
diff --git a/specs/objects/application-group.yaml b/specs/objects/application-group.yaml
index 0786e942..4a37721d 100644
--- a/specs/objects/application-group.yaml
+++ b/specs/objects/application-group.yaml
@@ -15,8 +15,10 @@ go_sdk_config:
- objects
- application
- group
-xpath_suffix:
-- application-group
+panos_xpath:
+ path:
+ - application-group
+ vars: []
locations:
- name: shared
xpath:
@@ -60,7 +62,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
diff --git a/specs/objects/application.yaml b/specs/objects/application.yaml
index cb2b752a..78cc782f 100644
--- a/specs/objects/application.yaml
+++ b/specs/objects/application.yaml
@@ -14,8 +14,10 @@ go_sdk_config:
package:
- objects
- application
-xpath_suffix:
-- application
+panos_xpath:
+ path:
+ - application
+ vars: []
locations:
- name: shared
xpath:
@@ -59,7 +61,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
diff --git a/specs/objects/custom-url-category.yaml b/specs/objects/custom-url-category.yaml
index f1f2a200..e3df0bce 100644
--- a/specs/objects/custom-url-category.yaml
+++ b/specs/objects/custom-url-category.yaml
@@ -16,9 +16,11 @@ go_sdk_config:
- objects
- profiles
- customurlcategory
-xpath_suffix:
-- profiles
-- custom-url-category
+panos_xpath:
+ path:
+ - profiles
+ - custom-url-category
+ vars: []
locations:
- name: shared
xpath:
@@ -62,7 +64,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
diff --git a/specs/objects/ephemeral-vm-auth-key.yaml b/specs/objects/ephemeral-vm-auth-key.yaml
index feddd542..3a682ba3 100644
--- a/specs/objects/ephemeral-vm-auth-key.yaml
+++ b/specs/objects/ephemeral-vm-auth-key.yaml
@@ -10,7 +10,8 @@ terraform_provider_config:
go_sdk_config:
skip: true
package: ["vmauthkey"] # unused
-xpath_suffix: ["vmauthkey"] # unused
+panos_xpath:
+ path: ["vmauthkey"] # unused
locations: []
entries: []
imports: []
diff --git a/specs/objects/external-dynamic-list.yaml b/specs/objects/external-dynamic-list.yaml
index 0550127a..b7ee926f 100644
--- a/specs/objects/external-dynamic-list.yaml
+++ b/specs/objects/external-dynamic-list.yaml
@@ -15,8 +15,10 @@ go_sdk_config:
package:
- objects
- extdynlist
-xpath_suffix:
-- external-list
+panos_xpath:
+ path:
+ - external-list
+ vars: []
locations:
- name: shared
xpath:
@@ -221,6 +223,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: five-minute
type: object
profiles:
@@ -232,6 +235,7 @@ spec:
variants: []
description: Every five minutes
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -243,6 +247,7 @@ spec:
variants: []
description: Everyhour
required: false
+ variant_group_id: 0
- name: monthly
type: object
profiles:
@@ -281,6 +286,7 @@ spec:
variants: []
description: Monthly
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -333,6 +339,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
- name: url
@@ -468,6 +475,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: five-minute
type: object
profiles:
@@ -479,6 +487,7 @@ spec:
variants: []
description: Every five minutes
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -490,6 +499,7 @@ spec:
variants: []
description: Everyhour
required: false
+ variant_group_id: 0
- name: monthly
type: object
profiles:
@@ -528,6 +538,7 @@ spec:
variants: []
description: Monthly
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -580,6 +591,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
- name: url
@@ -715,6 +727,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: five-minute
type: object
profiles:
@@ -726,6 +739,7 @@ spec:
variants: []
description: Every five minutes
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -737,6 +751,7 @@ spec:
variants: []
description: Everyhour
required: false
+ variant_group_id: 0
- name: monthly
type: object
profiles:
@@ -775,6 +790,7 @@ spec:
variants: []
description: Monthly
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -827,6 +843,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
- name: url
@@ -962,6 +979,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: five-minute
type: object
profiles:
@@ -973,6 +991,7 @@ spec:
variants: []
description: Every five minutes
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -984,6 +1003,7 @@ spec:
variants: []
description: Everyhour
required: false
+ variant_group_id: 0
- name: monthly
type: object
profiles:
@@ -1022,6 +1042,7 @@ spec:
variants: []
description: Monthly
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -1074,6 +1095,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
- name: url
@@ -1301,6 +1323,7 @@ spec:
variants: []
description: Everyday
required: false
+ variant_group_id: 0
- name: five-minute
type: object
profiles:
@@ -1312,6 +1335,7 @@ spec:
variants: []
description: Every five minutes
required: false
+ variant_group_id: 0
- name: hourly
type: object
profiles:
@@ -1323,6 +1347,7 @@ spec:
variants: []
description: Everyhour
required: false
+ variant_group_id: 0
- name: monthly
type: object
profiles:
@@ -1361,6 +1386,7 @@ spec:
variants: []
description: Monthly
required: false
+ variant_group_id: 0
- name: weekly
type: object
profiles:
@@ -1413,6 +1439,7 @@ spec:
variants: []
description: Once a week
required: false
+ variant_group_id: 0
description: ''
required: false
- name: url
diff --git a/specs/objects/profiles/antivirus.yaml b/specs/objects/profiles/antivirus.yaml
index 4ff772bb..6a144c9e 100644
--- a/specs/objects/profiles/antivirus.yaml
+++ b/specs/objects/profiles/antivirus.yaml
@@ -16,9 +16,11 @@ go_sdk_config:
- objects
- profiles
- antivirus
-xpath_suffix:
-- profiles
-- virus
+panos_xpath:
+ path:
+ - profiles
+ - virus
+ vars: []
locations:
- name: shared
xpath:
diff --git a/specs/objects/profiles/certificate.yaml b/specs/objects/profiles/certificate.yaml
index 2577f9f2..98c7a3de 100644
--- a/specs/objects/profiles/certificate.yaml
+++ b/specs/objects/profiles/certificate.yaml
@@ -15,7 +15,10 @@ go_sdk_config:
- device
- profile
- certificate
-xpath_suffix: []
+panos_xpath:
+ path:
+ - certificate
+ vars: []
locations:
- name: panorama
xpath:
@@ -204,6 +207,44 @@ entries:
imports: []
spec:
params:
+ - name: block-expired-certificate
+ type: bool
+ profiles:
+ - xpath:
+ - block-expired-cert
+ validators: []
+ spec: {}
+ description: Whether to block a session if certificate status is expired.
+ required: false
+ - name: block-timeout-certificate
+ type: bool
+ profiles:
+ - xpath:
+ - block-timeout-cert
+ validators: []
+ spec: {}
+ description: Whether to block a session if cert. status can't be retrieved within
+ timeout.
+ required: false
+ - name: block-unauthenticated-certificate
+ type: bool
+ profiles:
+ - xpath:
+ - block-unauthenticated-cert
+ validators: []
+ spec: {}
+ description: Whether to block session if the certificate was not issued to the
+ authenticating device.
+ required: false
+ - name: block-unknown-certificate
+ type: bool
+ profiles:
+ - xpath:
+ - block-unknown-cert
+ validators: []
+ spec: {}
+ description: Whether to block a session if cert. status is unknown.
+ required: false
- name: certificate
type: list
profiles:
@@ -259,44 +300,6 @@ spec:
variants: []
description: CA Certificate to assign to the profile.
required: false
- - name: block-expired-certificate
- type: bool
- profiles:
- - xpath:
- - block-expired-cert
- validators: []
- spec: {}
- description: Whether to block a session if certificate status is expired.
- required: false
- - name: block-timeout-certificate
- type: bool
- profiles:
- - xpath:
- - block-timeout-cert
- validators: []
- spec: {}
- description: Whether to block a session if cert. status can't be retrieved within
- timeout.
- required: false
- - name: block-unauthenticated-certificate
- type: bool
- profiles:
- - xpath:
- - block-unauthenticated-cert
- validators: []
- spec: {}
- description: Whether to block session if the certificate was not issued to the
- authenticating device.
- required: false
- - name: block-unknown-certificate
- type: bool
- profiles:
- - xpath:
- - block-unknown-cert
- validators: []
- spec: {}
- description: Whether to block a session if cert. status is unknown.
- required: false
- name: certificate-status-timeout
type: int64
profiles:
diff --git a/specs/objects/profiles/file-blocking.yaml b/specs/objects/profiles/file-blocking.yaml
index 1fe3ac1a..0332930d 100644
--- a/specs/objects/profiles/file-blocking.yaml
+++ b/specs/objects/profiles/file-blocking.yaml
@@ -15,9 +15,11 @@ go_sdk_config:
- objects
- profiles
- fileblocking
-xpath_suffix:
-- profiles
-- file-blocking
+panos_xpath:
+ path:
+ - profiles
+ - file-blocking
+ vars: []
locations:
- name: shared
xpath:
@@ -93,7 +95,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
diff --git a/specs/objects/profiles/ike-crypto-profile.yaml b/specs/objects/profiles/ike-crypto-profile.yaml
index a6c97733..db0ff675 100644
--- a/specs/objects/profiles/ike-crypto-profile.yaml
+++ b/specs/objects/profiles/ike-crypto-profile.yaml
@@ -15,11 +15,13 @@ go_sdk_config:
- objects
- profiles
- ikecrypto
-xpath_suffix:
-- network
-- ike
-- crypto-profiles
-- ike-crypto-profiles
+panos_xpath:
+ path:
+ - network
+ - ike
+ - crypto-profiles
+ - ike-crypto-profiles
+ vars: []
locations:
- name: ngfw
xpath:
diff --git a/specs/objects/profiles/ipsec-crypto-profile.yaml b/specs/objects/profiles/ipsec-crypto-profile.yaml
index bd9f5cc1..652faa4b 100644
--- a/specs/objects/profiles/ipsec-crypto-profile.yaml
+++ b/specs/objects/profiles/ipsec-crypto-profile.yaml
@@ -15,11 +15,13 @@ go_sdk_config:
- objects
- profiles
- ipseccrypto
-xpath_suffix:
-- network
-- ike
-- crypto-profiles
-- ipsec-crypto-profiles
+panos_xpath:
+ path:
+ - network
+ - ike
+ - crypto-profiles
+ - ipsec-crypto-profiles
+ vars: []
locations:
- name: ngfw
xpath:
@@ -317,6 +319,7 @@ spec:
variants: []
description: AH only
required: false
+ variant_group_id: 0
- name: esp
type: object
profiles:
@@ -375,3 +378,4 @@ spec:
variants: []
description: ESP options
required: false
+ variant_group_id: 0
diff --git a/specs/objects/profiles/log-forwarding.yaml b/specs/objects/profiles/log-forwarding.yaml
index 81f44f38..acbd2414 100644
--- a/specs/objects/profiles/log-forwarding.yaml
+++ b/specs/objects/profiles/log-forwarding.yaml
@@ -15,9 +15,11 @@ go_sdk_config:
- objects
- profiles
- logforwarding
-xpath_suffix:
-- log-settings
-- profiles
+panos_xpath:
+ path:
+ - log-settings
+ - profiles
+ vars: []
locations:
- name: shared
xpath:
diff --git a/specs/objects/profiles/security-profile-group.yaml b/specs/objects/profiles/security-profile-group.yaml
index cb824336..137ea183 100644
--- a/specs/objects/profiles/security-profile-group.yaml
+++ b/specs/objects/profiles/security-profile-group.yaml
@@ -15,8 +15,10 @@ go_sdk_config:
- objects
- profiles
- secgroup
-xpath_suffix:
-- profile-group
+panos_xpath:
+ path:
+ - profile-group
+ vars: []
locations:
- name: shared
xpath:
diff --git a/specs/objects/profiles/ssl-tls-service.yaml b/specs/objects/profiles/ssl-tls-service.yaml
index 3ed7bbc7..c6f892a6 100644
--- a/specs/objects/profiles/ssl-tls-service.yaml
+++ b/specs/objects/profiles/ssl-tls-service.yaml
@@ -16,8 +16,10 @@ go_sdk_config:
- device
- profile
- ssltls
-xpath_suffix:
-- ssl-tls-service-profile
+panos_xpath:
+ path:
+ - ssl-tls-service-profile
+ vars: []
locations:
- name: shared
xpath:
@@ -51,7 +53,8 @@ locations:
- template
- $template
- config
- - shared
+ - devices
+ - $ngfw_device
vars:
- name: panorama_device
description: Specific Panorama device
@@ -64,13 +67,19 @@ locations:
required: true
validators: []
type: entry
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
description: Located in a specific template
devices:
- panorama
validators: []
required: false
read_only: false
-- name: template_vsys
+- name: template-vsys
xpath:
path:
- config
@@ -128,7 +137,8 @@ locations:
- template-stack
- $template_stack
- config
- - shared
+ - devices
+ - $ngfw_device
vars:
- name: panorama_device
description: Specific Panorama device
@@ -137,11 +147,17 @@ locations:
validators: []
type: entry
- name: template_stack
- description: The template stack
+ description: Specific Panorama template stack
required: true
validators: []
type: entry
- description: Located in a specific template
+ - name: ngfw_device
+ description: The NGFW device
+ required: false
+ default: localhost.localdomain
+ validators: []
+ type: entry
+ description: Located in a specific template stack
devices:
- panorama
validators: []
@@ -226,33 +242,6 @@ spec:
validators: []
spec:
params:
- - name: allow-authentication-sha1
- type: bool
- profiles:
- - xpath:
- - auth-algo-sha1
- validators: []
- spec: {}
- description: Allow authentication SHA1
- required: false
- - name: allow-authentication-sha256
- type: bool
- profiles:
- - xpath:
- - auth-algo-sha256
- validators: []
- spec: {}
- description: Allow authentication SHA256
- required: false
- - name: allow-authentication-sha384
- type: bool
- profiles:
- - xpath:
- - auth-algo-sha384
- validators: []
- spec: {}
- description: Allow authentication SHA384
- required: false
- name: allow-algorithm-3des
type: bool
profiles:
@@ -298,15 +287,6 @@ spec:
spec: {}
description: Allow algorithm AES-256-GCM
required: false
- - name: allow-algorithm-rc4
- type: bool
- profiles:
- - xpath:
- - enc-algo-rc4
- validators: []
- spec: {}
- description: Allow algorithm RC4
- required: false
- name: allow-algorithm-dhe
type: bool
profiles:
@@ -325,6 +305,15 @@ spec:
spec: {}
description: Allow algorithm ECDHE
required: false
+ - name: allow-algorithm-rc4
+ type: bool
+ profiles:
+ - xpath:
+ - enc-algo-rc4
+ validators: []
+ spec: {}
+ description: Allow algorithm RC4
+ required: false
- name: allow-algorithm-rsa
type: bool
profiles:
@@ -334,6 +323,33 @@ spec:
spec: {}
description: Allow algorithm RSA
required: false
+ - name: allow-authentication-sha1
+ type: bool
+ profiles:
+ - xpath:
+ - auth-algo-sha1
+ validators: []
+ spec: {}
+ description: Allow authentication SHA1
+ required: false
+ - name: allow-authentication-sha256
+ type: bool
+ profiles:
+ - xpath:
+ - auth-algo-sha256
+ validators: []
+ spec: {}
+ description: Allow authentication SHA256
+ required: false
+ - name: allow-authentication-sha384
+ type: bool
+ profiles:
+ - xpath:
+ - auth-algo-sha384
+ validators: []
+ spec: {}
+ description: Allow authentication SHA384
+ required: false
- name: max-version
type: enum
profiles:
diff --git a/specs/objects/profiles/url-filtering.yaml b/specs/objects/profiles/url-filtering.yaml
index 98f49bcb..02295870 100644
--- a/specs/objects/profiles/url-filtering.yaml
+++ b/specs/objects/profiles/url-filtering.yaml
@@ -15,9 +15,11 @@ go_sdk_config:
- objects
- profiles
- urlfiltering
-xpath_suffix:
-- profiles
-- url-filtering
+panos_xpath:
+ path:
+ - profiles
+ - url-filtering
+ vars: []
locations:
- name: shared
xpath:
diff --git a/specs/objects/profiles/vulnerability.yaml b/specs/objects/profiles/vulnerability.yaml
index 5faec089..03c3b453 100644
--- a/specs/objects/profiles/vulnerability.yaml
+++ b/specs/objects/profiles/vulnerability.yaml
@@ -15,9 +15,11 @@ go_sdk_config:
- objects
- profiles
- vulnerability
-xpath_suffix:
-- profiles
-- vulnerability
+panos_xpath:
+ path:
+ - profiles
+ - vulnerability
+ vars: []
locations:
- name: shared
xpath:
@@ -71,6 +73,17 @@ entries:
imports: []
spec:
params:
+ - name: cloud-inline-analysis
+ type: bool
+ profiles:
+ - xpath:
+ - cloud-inline-analysis
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec: {}
+ description: Enable cloud inline analysis
+ required: false
- name: description
type: string
profiles:
@@ -101,6 +114,79 @@ spec:
- value: 'no'
description: disable object override in child device groups
required: false
+ - name: inline-exception-edl-url
+ type: list
+ profiles:
+ - xpath:
+ - inline-exception-edl-url
+ type: member
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec:
+ type: string
+ items:
+ type: string
+ description: ''
+ required: false
+ - name: inline-exception-ip-address
+ type: list
+ profiles:
+ - xpath:
+ - inline-exception-ip-address
+ type: member
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec:
+ type: string
+ items:
+ type: string
+ description: ''
+ required: false
+ - name: mica-engine-vulnerability-enabled
+ type: list
+ profiles:
+ - xpath:
+ - mica-engine-vulnerability-enabled
+ - entry
+ type: entry
+ min_version: 11.0.2
+ max_version: 11.0.3
+ validators: []
+ spec:
+ type: object
+ items:
+ type: object
+ spec:
+ params:
+ - name: inline-policy-action
+ type: enum
+ profiles:
+ - xpath:
+ - inline-policy-action
+ validators:
+ - type: values
+ spec:
+ values:
+ - alert
+ - allow
+ - reset-both
+ - reset-client
+ - reset-server
+ spec:
+ default: alert
+ values:
+ - value: alert
+ - value: allow
+ - value: reset-both
+ - value: reset-client
+ - value: reset-server
+ description: ''
+ required: false
+ variants: []
+ description: ''
+ required: false
- name: rules
type: list
profiles:
@@ -585,88 +671,4 @@ spec:
variants: []
description: ''
required: false
- - name: cloud-inline-analysis
- type: bool
- profiles:
- - xpath:
- - cloud-inline-analysis
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec: {}
- description: Enable cloud inline analysis
- required: false
- - name: inline-exception-edl-url
- type: list
- profiles:
- - xpath:
- - inline-exception-edl-url
- type: member
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec:
- type: string
- items:
- type: string
- description: ''
- required: false
- - name: inline-exception-ip-address
- type: list
- profiles:
- - xpath:
- - inline-exception-ip-address
- type: member
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec:
- type: string
- items:
- type: string
- description: ''
- required: false
- - name: mica-engine-vulnerability-enabled
- type: list
- profiles:
- - xpath:
- - mica-engine-vulnerability-enabled
- - entry
- type: entry
- min_version: 11.0.2
- max_version: 11.0.3
- validators: []
- spec:
- type: object
- items:
- type: object
- spec:
- params:
- - name: inline-policy-action
- type: enum
- profiles:
- - xpath:
- - inline-policy-action
- validators:
- - type: values
- spec:
- values:
- - alert
- - allow
- - reset-both
- - reset-client
- - reset-server
- spec:
- default: alert
- values:
- - value: alert
- - value: allow
- - value: reset-both
- - value: reset-client
- - value: reset-server
- description: ''
- required: false
- variants: []
- description: ''
- required: false
variants: []
diff --git a/specs/objects/profiles/wildfire-analysis.yaml b/specs/objects/profiles/wildfire-analysis.yaml
index 3f2d26e6..0a0f3b19 100644
--- a/specs/objects/profiles/wildfire-analysis.yaml
+++ b/specs/objects/profiles/wildfire-analysis.yaml
@@ -15,9 +15,11 @@ go_sdk_config:
- objects
- profiles
- wildfireanalysis
-xpath_suffix:
-- profiles
-- wildfire-analysis
+panos_xpath:
+ path:
+ - profiles
+ - wildfire-analysis
+ vars: []
locations:
- name: shared
xpath:
diff --git a/specs/objects/service-group.yaml b/specs/objects/service-group.yaml
index 37ba9b81..b45e44f5 100644
--- a/specs/objects/service-group.yaml
+++ b/specs/objects/service-group.yaml
@@ -16,8 +16,10 @@ go_sdk_config:
- objects
- service
- group
-xpath_suffix:
-- service-group
+panos_xpath:
+ path:
+ - service-group
+ vars: []
locations:
- name: shared
xpath:
@@ -61,7 +63,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
diff --git a/specs/objects/service.yaml b/specs/objects/service.yaml
index 0be2d200..13a81a04 100644
--- a/specs/objects/service.yaml
+++ b/specs/objects/service.yaml
@@ -15,8 +15,10 @@ go_sdk_config:
package:
- objects
- service
-xpath_suffix:
-- service
+panos_xpath:
+ path:
+ - service
+ vars: []
locations:
- name: shared
xpath:
@@ -60,7 +62,6 @@ locations:
description: Located in a specific Virtual System
devices:
- ngfw
- - panorama
validators: []
required: false
read_only: false
@@ -148,33 +149,6 @@ spec:
validators: []
spec:
params:
- - name: port
- type: string
- profiles:
- - xpath:
- - port
- validators:
- - type: length
- spec:
- max: 1023
- spec: {}
- description: ''
- required: false
- codegen_overrides:
- terraform:
- name: destination-port
- - name: source-port
- type: string
- profiles:
- - xpath:
- - source-port
- validators:
- - type: length
- spec:
- max: 1023
- spec: {}
- description: ''
- required: false
- name: override
type: object
profiles:
@@ -226,17 +200,6 @@ spec:
variants: []
description: ''
required: false
- variants: []
- description: ''
- required: false
- - name: udp
- type: object
- profiles:
- - xpath:
- - udp
- validators: []
- spec:
- params:
- name: port
type: string
profiles:
@@ -264,6 +227,17 @@ spec:
spec: {}
description: ''
required: false
+ variants: []
+ description: ''
+ required: false
+ - name: udp
+ type: object
+ profiles:
+ - xpath:
+ - udp
+ validators: []
+ spec:
+ params:
- name: override
type: object
profiles:
@@ -290,6 +264,33 @@ spec:
variants: []
description: ''
required: false
+ - name: port
+ type: string
+ profiles:
+ - xpath:
+ - port
+ validators:
+ - type: length
+ spec:
+ max: 1023
+ spec: {}
+ description: ''
+ required: false
+ codegen_overrides:
+ terraform:
+ name: destination-port
+ - name: source-port
+ type: string
+ profiles:
+ - xpath:
+ - source-port
+ validators:
+ - type: length
+ spec:
+ max: 1023
+ spec: {}
+ description: ''
+ required: false
variants: []
description: ''
required: false
diff --git a/specs/panorama/device-group-parent.yaml b/specs/panorama/device-group-parent.yaml
index de5727b2..807c0782 100644
--- a/specs/panorama/device-group-parent.yaml
+++ b/specs/panorama/device-group-parent.yaml
@@ -12,8 +12,9 @@ terraform_provider_config:
go_sdk_config:
skip: true
package: ["device_group_parent"]
-xpath_suffix:
- - device-group
+panos_xpath:
+ path:
+ - device-group
locations:
- name: "panorama"
description: "Located in a specific Panorama."
diff --git a/specs/panorama/device-group.yaml b/specs/panorama/device-group.yaml
index f757d4e2..7b46c07a 100644
--- a/specs/panorama/device-group.yaml
+++ b/specs/panorama/device-group.yaml
@@ -1,12 +1,14 @@
name: "Device group"
terraform_provider_config:
+ resource_type: entry
suffix: "device_group"
go_sdk_config:
package:
- "panorama"
- "devicegroup"
-xpath_suffix:
- - "device-group"
+panos_xpath:
+ path:
+ - "device-group"
locations:
- name: "panorama"
description: "Located in a specific Panorama."
diff --git a/specs/panorama/template-stack.yaml b/specs/panorama/template-stack.yaml
index 0c0b4504..b5a1fced 100644
--- a/specs/panorama/template-stack.yaml
+++ b/specs/panorama/template-stack.yaml
@@ -1,12 +1,14 @@
name: "Template stack"
terraform_provider_config:
+ resource_type: entry
suffix: "template_stack"
go_sdk_config:
package:
- "panorama"
- "template_stack"
-xpath_suffix:
- - "template-stack"
+panos_xpath:
+ path:
+ - "template-stack"
locations:
- name: "panorama"
description: "Located in a specific Panorama."
@@ -58,7 +60,7 @@ spec:
items:
type: string
profiles:
- - type: entry
+ - type: member
xpath: ["devices"]
- name: default-vsys
description: "Default virtual system"
diff --git a/specs/panorama/template-variable.yaml b/specs/panorama/template-variable.yaml
index 2b1a2e0f..b22c5831 100644
--- a/specs/panorama/template-variable.yaml
+++ b/specs/panorama/template-variable.yaml
@@ -1,12 +1,14 @@
name: "Template Variable"
terraform_provider_config:
+ resource_type: entry
suffix: "template_variable"
go_sdk_config:
package:
- "panorama"
- "template_variable"
-xpath_suffix:
- - "variable"
+panos_xpath:
+ path:
+ - "variable"
locations:
- name: "template"
description: "Located in a specific template."
diff --git a/specs/panorama/template.yaml b/specs/panorama/template.yaml
index be078ac6..f1b52008 100644
--- a/specs/panorama/template.yaml
+++ b/specs/panorama/template.yaml
@@ -1,12 +1,14 @@
name: "Template"
terraform_provider_config:
+ resource_type: entry
suffix: "template"
go_sdk_config:
package:
- "panorama"
- "template"
-xpath_suffix:
- - "template"
+panos_xpath:
+ path:
+ - "template"
locations:
- name: "panorama"
description: "Located in a specific Panorama."
diff --git a/specs/policies/decryption-policy.yaml b/specs/policies/decryption-policy.yaml
index 7629bad2..291a5a8f 100644
--- a/specs/policies/decryption-policy.yaml
+++ b/specs/policies/decryption-policy.yaml
@@ -17,9 +17,11 @@ go_sdk_config:
- policies
- rules
- decryption
-xpath_suffix:
-- decryption
-- rules
+panos_xpath:
+ path:
+ - decryption
+ - rules
+ vars: []
locations:
- name: shared
xpath:
diff --git a/specs/policies/network-address-translation.yaml b/specs/policies/network-address-translation.yaml
index 5363b37e..7001881d 100644
--- a/specs/policies/network-address-translation.yaml
+++ b/specs/policies/network-address-translation.yaml
@@ -17,9 +17,11 @@ go_sdk_config:
- policies
- rules
- nat
-xpath_suffix:
-- nat
-- rules
+panos_xpath:
+ path:
+ - nat
+ - rules
+ vars: []
locations:
- name: shared
xpath:
@@ -317,6 +319,7 @@ spec:
spec: {}
description: Floating IP address in HA Active-Active configuration
required: false
+ variant_group_id: 0
- name: ip
type: string
profiles:
@@ -327,8 +330,10 @@ spec:
description: specify exact IP address if interface has multiple
addresses
required: false
+ variant_group_id: 0
description: Use interface address as translated address
required: false
+ variant_group_id: 0
- name: translated-address
type: list
profiles:
@@ -342,6 +347,7 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: Fallback Dynamic IP and port translation
required: false
- name: translated-address
@@ -360,6 +366,7 @@ spec:
variants: []
description: Dynamic IP-only translation
required: false
+ variant_group_id: 0
- name: dynamic-ip-and-port
type: object
profiles:
@@ -399,6 +406,7 @@ spec:
spec: {}
description: Floating IP address in HA Active-Active configuration
required: false
+ variant_group_id: 0
- name: ip
type: string
profiles:
@@ -408,8 +416,10 @@ spec:
spec: {}
description: specify exact IP address if interface has multiple addresses
required: false
+ variant_group_id: 0
description: Use interface address as translated address
required: false
+ variant_group_id: 0
- name: translated-address
type: list
profiles:
@@ -423,8 +433,10 @@ spec:
type: string
description: ''
required: false
+ variant_group_id: 0
description: Dynamic IP and port translation
required: false
+ variant_group_id: 0
- name: static-ip
type: object
profiles:
@@ -464,6 +476,7 @@ spec:
variants: []
description: static IP translation via IP shifting
required: false
+ variant_group_id: 0
description: ''
required: false
- name: tag
@@ -599,28 +612,6 @@ spec:
validators: []
spec:
params:
- - name: translated-address
- type: string
- profiles:
- - xpath:
- - translated-address
- validators: []
- spec: {}
- description: ''
- required: false
- - name: translated-port
- type: int64
- profiles:
- - xpath:
- - translated-port
- validators:
- - type: length
- spec:
- min: 1
- max: 65535
- spec: {}
- description: ''
- required: false
- name: dns-rewrite
type: object
profiles:
@@ -650,12 +641,36 @@ spec:
variants: []
description: ''
required: false
+ variant_group_id: 0
+ - name: translated-address
+ type: string
+ profiles:
+ - xpath:
+ - translated-address
+ validators: []
+ spec: {}
+ description: ''
+ required: false
+ - name: translated-port
+ type: int64
+ profiles:
+ - xpath:
+ - translated-port
+ validators:
+ - type: length
+ spec:
+ min: 1
+ max: 65535
+ spec: {}
+ description: ''
+ required: false
variants: []
description: ''
required: false
codegen_overrides:
terraform:
variant_check: ConflictsWith
+ variant_group_id: 0
- name: dynamic-destination-translation
type: object
profiles:
@@ -716,3 +731,4 @@ spec:
codegen_overrides:
terraform:
variant_check: ConflictsWith
+ variant_group_id: 0
diff --git a/specs/policies/security-policy-rule.yaml b/specs/policies/security-policy-rule.yaml
index 4223219c..13f5a549 100644
--- a/specs/policies/security-policy-rule.yaml
+++ b/specs/policies/security-policy-rule.yaml
@@ -17,9 +17,11 @@ go_sdk_config:
- policies
- rules
- security
-xpath_suffix:
-- security
-- rules
+panos_xpath:
+ path:
+ - security
+ - rules
+ vars: []
locations:
- name: shared
xpath:
@@ -233,6 +235,16 @@ spec:
spec: {}
description: ''
required: false
+ - name: disable-server-response-inspection
+ type: bool
+ profiles:
+ - xpath:
+ - option
+ - disable-server-response-inspection
+ validators: []
+ spec: {}
+ description: Disable inspection of server side traffic
+ required: false
- name: disabled
type: bool
profiles:
@@ -778,14 +790,4 @@ spec:
codegen_overrides:
terraform:
private: true
- - name: disable-server-response-inspection
- type: bool
- profiles:
- - xpath:
- - option
- - disable-server-response-inspection
- validators: []
- spec: {}
- description: Disable inspection of server side traffic
- required: false
variants: []
diff --git a/specs/schema/import.schema.json b/specs/schema/import.schema.json
index 19626edb..415a8aef 100644
--- a/specs/schema/import.schema.json
+++ b/specs/schema/import.schema.json
@@ -14,8 +14,14 @@
"additionalProperties": false,
"properties": {
"name": { "type": "string" },
+ "description": { "type": "string" },
+ "read_only": { "type": "boolean" },
"required": { "type": "boolean", "default": false },
- "xpath": { "$ref": "xpath.schema.json" }
+ "xpath": { "$ref": "xpath.schema.json" },
+ "validators": {
+ "type": "array",
+ "items": { "$ref": "validator.schema.json" }
+ }
}
}
}
diff --git a/specs/schema/object.schema.json b/specs/schema/object.schema.json
index 68121838..87fe9c73 100644
--- a/specs/schema/object.schema.json
+++ b/specs/schema/object.schema.json
@@ -9,6 +9,7 @@
"name",
"terraform_provider_config",
"go_sdk_config",
+ "panos_xpath",
"locations",
"spec"
],
@@ -17,7 +18,7 @@
"terraform_provider_config": {
"type": "object",
"additionalProperties": false,
- "required": ["suffix"],
+ "required": ["suffix", "resource_type"],
"properties": {
"skip_datasource": { "type": "boolean" },
"skip_resource": { "type": "boolean" },
@@ -67,10 +68,16 @@
}
}
},
- "xpath_suffix": {
- "type": "array",
- "items": {
- "type": "string"
+ "panos_xpath": {
+ "type": "object",
+ "required": ["path"],
+ "properties": {
+ "path": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
}
},
"locations": {
diff --git a/specs/schema/schema.json b/specs/schema/schema.json
index c9f101ae..de3ef738 100644
--- a/specs/schema/schema.json
+++ b/specs/schema/schema.json
@@ -8,7 +8,7 @@
"name",
"terraform_provider_config",
"go_sdk_config",
- "xpath_suffix",
+ "panos_xpath",
"locations",
"entries",
"version",
@@ -26,6 +26,13 @@
"type": "string"
}
}
+ },
+ "panos_xpath": {
+ "type": "object",
+ "required": ["path"],
+ "properties": [
+ "path": { "type": "array" }
+ ]
}
}
}
diff --git a/specs/schema/spec.schema.json b/specs/schema/spec.schema.json
index ca825c4d..b84f5eac 100644
--- a/specs/schema/spec.schema.json
+++ b/specs/schema/spec.schema.json
@@ -21,6 +21,7 @@
"properties": {
"name": { "type": "string" },
"description": { "type": "string" },
+ "variant_group_id": { "type": "integer" },
"codegen_overrides": {
"type": "object",
"additionalProperties": false,
diff --git a/templates/sdk/config.tmpl b/templates/sdk/config.tmpl
index 1b90d258..8ebddb74 100644
--- a/templates/sdk/config.tmpl
+++ b/templates/sdk/config.tmpl
@@ -5,128 +5,12 @@ type configXmlContainer{{createGoSuffixFromVersion $.Version }} struct {
}
{{- end }}
-{{- define "configXmlStructTmpl" }}
-type configXml{{createGoSuffixFromVersion $.Version}} struct {
- XMLName xml.Name `xml:"system"`
- {{- range $_, $param := $.Spec.Params}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
- {{- end}}
-
- {{- range $_, $param := $.Spec.OneOf}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
- {{- end}}
-
- Misc []generic.Xml `xml:",any"`
-}
-{{- end }}
-
-{{- define "configXmlChildStructTmpl" }}
-type {{ $.Name }}Xml{{ createGoSuffixFromVersion $.Version }} struct {
-{{- range $_, $param := $.Spec.Params}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
-{{- end}}
-
-{{- range $_, $param := $.Spec.OneOf}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
-{{- end}}
-
- Misc []generic.Xml `xml:",any"`
-}
-{{- end }}
-
-{{- define "SpecifyConfigTmpl" }}
-func specifyConfig{{createGoSuffixFromVersion $.Version}}(o *Config) (any, error) {
- config := configXml{{createGoSuffixFromVersion $.Version}}{}
-
- {{- range $_, $param := $.Spec.Params}}
- {{ specifyEntryAssignment "config" $param $.Version }}
- {{- end}}
-
- {{- range $_, $param := $.Spec.OneOf}}
- {{ specifyEntryAssignment "config" $param $.Version }}
- {{- end}}
-
- config.Misc = o.Misc["Config"]
-
- return config, nil
-}
-{{- end }}
-
-{{- define "NormalizeTmpl" }}
-func (c *configXmlContainer{{createGoSuffixFromVersion $.Version }}) Normalize() ([]*Config, error) {
- configList := make([]*Config, 0, len(c.Answer))
- for _, o := range c.Answer {
- config := &Config{
- Misc: make(map[string][]generic.Xml),
- }
-
- {{- range $_, $param := $.Spec.Params}}
- {{normalizeAssignment "config" $param $.Version}}
- {{- end}}
-
- {{- range $_, $param := $.Spec.OneOf}}
- {{normalizeAssignment "config" $param $.Version}}
- {{- end}}
-
- config.Misc["Config"] = o.Misc
-
- configList = append(configList, config)
-}
-
-return configList, nil
-}
-{{- end }}
-
{{- if not .Entry}}
package {{packageName .GoSdkPath}}
{{renderImports "config"}}
- type Config{{createGoSuffixFromVersion nil}} struct {
- {{- range $_, $param := $.Spec.SortedParams}}
- {{$param.Name.CamelCase}} {{specParamType "" $param}}
- {{- end}}
- {{- range $_, $param := $.Spec.SortedOneOf}}
- {{$param.Name.CamelCase}} {{specParamType "" $param}}
- {{- end}}
-
- Misc map[string][]generic.Xml
- }
-
- {{- range $name, $nested := nestedSpecs $.Spec }}
- type {{$name}}{{createGoSuffixFromVersion nil}} struct {
- {{- range $_, $param := $nested.Spec.SortedParams}}
- {{$param.Name.CamelCase}} {{specParamType $name $param}}
- {{- end}}
- {{- range $_, $param := $nested.Spec.SortedOneOf}}
- {{$param.Name.CamelCase}} {{specParamType $name $param}}
- {{- end}}
- }
- {{- end}}
+ {{- RenderApiStructs $ }}
{{- template "configXmlContainerStructTmpl" Map "Version" nil }}
@@ -134,20 +18,13 @@ return configList, nil
{{- template "configXmlContainerStructTmpl" Map "Version" $version.Minimum }}
{{- end}}
- {{- template "configXmlStructTmpl" Map "Spec" $.Spec "Version" nil }}
- {{- range $version := .SupportedVersionRanges }}
- {{- template "configXmlStructTmpl" Map "Version" $version.Minimum }}
- {{- end}}
+ {{ RenderXmlContainerNormalizers $ }}
- {{- range $name, $nested := nestedSpecs $.Spec }}
- {{- template "configXmlChildStructTmpl" Map "Name" $name "ParentIsList" $nested.ParentIsList "Spec" $nested.Spec "Version" nil }}
- {{- end }}
+ {{ RenderXmlContainerSpecifiers $ }}
- {{- range $version := .SupportedVersionRanges }}
- {{- range $name, $nested := nestedSpecs $.Spec }}
- {{- template "configXmlChildStructTmpl" Map "Name" $name "ParentIsList" $nested.ParentIsList "Spec" $nested.Spec "Version" $version.Minimum }}
- {{- end}}
- {{- end}}
+ {{- RenderXmlStructs $ }}
+
+ {{ RenderToXmlMarshallers $ }}
func Versioning(vn version.Number) (Specifier, Normalizer, error) {
{{- $numberOfVersions := len .SupportedVersions }}
@@ -179,38 +56,5 @@ return configList, nil
{{- end}}
}
- {{- template "SpecifyConfigTmpl" Map "Spec" $.Spec "Version" nil }}
-
- {{- range $version := .SupportedVersionRanges }}
- {{- template "SpecifyConfigTmpl" Map "Spec" $.Spec "Version" nil }}
- {{- end }}
-
- {{- template "NormalizeTmpl" Map "Spec" $.Spec "Version" nil }}
- {{- range $version := .SupportedVersionRanges }}
- {{- template "NormalizeTmpl" Map "Spec" $.Spec "Version" $version.Minimum }}
- {{- end}}
-
- func SpecMatches(a, b *Config) bool {
- if a == nil && b != nil || a != nil && b == nil {
- return false
- } else if a == nil && b == nil {
- return true
- }
-
- // Don't compare Name.
- {{- range $_, $param := .Spec.SortedParams}}
- if !{{specMatchesFunction $param}}(a.{{$param.Name.CamelCase}}, b.{{$param.Name.CamelCase}}) {
- return false
- }
- {{- end}}
- {{- range $_, $param := .Spec.SortedOneOf}}
- if !{{specMatchesFunction $param}}(a.{{$param.Name.CamelCase}}, b.{{$param.Name.CamelCase}}) {
- return false
- }
- {{- end}}
-
- return true
- }
-
- {{nestedSpecMatchesFunction $.Spec}}
+ {{- RenderSpecMatchers $ }}
{{- end}}
diff --git a/templates/sdk/entry.tmpl b/templates/sdk/entry.tmpl
index 764057af..aa41fedf 100644
--- a/templates/sdk/entry.tmpl
+++ b/templates/sdk/entry.tmpl
@@ -1,105 +1,3 @@
-{{- define "entryXmlStructTmpl" }}
-type entryXml{{createGoSuffixFromVersion $.Version}} struct {
- XMLName xml.Name `xml:"entry"`
- Name string `xml:"name,attr"`
- {{- range $_, $param := $.Spec.Params}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
- {{- end}}
-
- {{- range $_, $param := $.Spec.OneOf}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType "" $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
- {{- end}}
-
- Misc []generic.Xml `xml:",any"`
-}
-{{- end }}
-
-{{- define "entryXmlChildStructTmpl" }}
-type {{ .Name }}Xml{{createGoSuffixFromVersion $.Version}} struct {
- {{- range $_, $param := $.Spec.Params}}
- {{- if and ($.ParentIsList) (eq $param.Name.CamelCase "Name") }}
- XMLName xml.Name `xml:"entry"`
- {{- end}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
- {{- end}}
-
- {{- range $_, $param := $.Spec.OneOf}}
- {{- if paramSupportedInVersion $param $.Version}}
- {{- if $param.Spec}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}}{{createGoSuffixFromVersion $.Version}} {{xmlTag $param}}
- {{- else}}
- {{$param.Name.CamelCase}} {{xmlParamType $.Name $param}} {{xmlTag $param}}
- {{- end}}
- {{- end}}
- {{- end}}
-
- Misc []generic.Xml `xml:",any"`
-}
-{{- end }}
-
-{{- define "SpecifyEntryTmpl" }}
-func specifyEntry{{ createGoSuffixFromVersion $.Version }}(o *Entry) (any, error) {
- entry := entryXml{{ createGoSuffixFromVersion $.Version }}{}
- entry.Name = o.Name
-
- {{- range $_, $param := $.Spec.Params}}
- {{ specifyEntryAssignment "entry" $param $.Version }}
- {{- end}}
-
- {{- range $_, $param := $.Spec.OneOf}}
- {{ specifyEntryAssignment "entry" $param $.Version }}
- {{- end}}
-
- entry.Misc = o.Misc["Entry"]
-
- return entry, nil
-}
-
-{{- end }}
-
-{{- define "NormalizeTmpl" }}
-func (c *entryXmlContainer{{ createGoSuffixFromVersion $.Version }}) Normalize() ([]*Entry, error) {
- entryList := make([]*Entry, 0, len(c.Answer))
- for _, o := range c.Answer {
- entry := &Entry{
- Misc: make(map[string][]generic.Xml),
- }
- entry.Name = o.Name
- {{- range $_, $param := $.Spec.Params}}
- {{normalizeAssignment "entry" $param $.Version }}
- {{- end}}
-
- {{- range $_, $param := $.Spec.OneOf}}
- {{normalizeAssignment "entry" $param $.Version }}
- {{- end}}
-
- entry.Misc["Entry"] = o.Misc
-
- entryList = append(entryList, entry)
-}
-
-return entryList, nil
-}
-{{- end }}
-
{{- if .Entry}}
package {{packageName .GoSdkPath}}
@@ -110,35 +8,14 @@ return entryList, nil
)
var (
- Suffix = []string{
+ suffix = []string{
{{- $length := subtract (len .XpathSuffix) 1 }}
{{- range $index, $suffix := .XpathSuffix}}"
{{- $suffix}}"{{- if lt $index $length}},{{- end}}
{{- end}}}
)
- type Entry{{createGoSuffixFromVersion nil}} struct {
- Name string
- {{- range $_, $param := $.Spec.Params}}
- {{$param.Name.CamelCase}} {{specParamType "" $param}}
- {{- end}}
- {{- range $_, $param := $.Spec.OneOf}}
- {{$param.Name.CamelCase}} {{specParamType "" $param}}
- {{- end}}
-
- Misc map[string][]generic.Xml
- }
-
- {{ range $name, $nested := nestedSpecs $.Spec }}
- type {{$name}}{{createGoSuffixFromVersion nil}} struct {
- {{- range $param := $nested.Spec.SortedParams}}
- {{$param.Name.CamelCase}} {{specParamType $name $param}}
- {{- end}}
- {{- range $param := $nested.Spec.SortedOneOf}}
- {{$param.Name.CamelCase}} {{specParamType $name $param}}
- {{- end}}
- }
- {{- end}}
+ {{ RenderApiStructs $ }}
type entryXmlContainer{{createGoSuffixFromVersion nil}} struct {
Answer []entryXml{{createGoSuffixFromVersion nil}} `xml:"entry"`
@@ -150,20 +27,13 @@ return entryList, nil
}
{{- end}}
- {{- template "entryXmlStructTmpl" Map "Spec" $.Spec "Version" nil }}
- {{- range $version := .SupportedVersionRanges }}
- {{- template "entryXmlStructTmpl" Map "Spec" $.Spec "Version" $version.Minimum }}
- {{- end}}
+ {{ RenderXmlContainerNormalizers $ }}
- {{- range $name, $nested := nestedSpecs $.Spec }}
- {{- template "entryXmlChildStructTmpl" Map "Name" $name "ParentIsList" $nested.ParentIsList "Spec" $nested.Spec "Version" nil }}
- {{- end }}
+ {{ RenderXmlContainerSpecifiers $ }}
- {{- range $version := .SupportedVersionRanges }}
- {{- range $name, $nested := nestedSpecs $.Spec }}
- {{- template "entryXmlChildStructTmpl" Map "Name" $name "ParentIsList" $nested.ParentIsList "Spec" $nested.Spec "Version" $version.Minimum }}
- {{- end }}
- {{- end}}
+ {{ RenderXmlStructs $ }}
+
+ {{ RenderToXmlMarshallers $ }}
{{ range $name, $const := .Const}}
const (
@@ -179,6 +49,7 @@ return entryList, nil
}
{{- range $_, $param := .Spec.SortedParams}}
+ {{- if not (paramNotSkipped $param) }}{{ continue }}{{- end }}
if v == "{{$param.Name.Underscore}}" || v == "{{$param.Name.CamelCase}}" {
return e.{{$param.Name.CamelCase}}, nil
}
@@ -211,41 +82,7 @@ return entryList, nil
return specifyEntry, &entryXmlContainer{}, nil
}
-
- {{- template "SpecifyEntryTmpl" Map "Spec" $.Spec "Version" nil }}
-
- {{ range $version := .SupportedVersionRanges }}
- {{- template "SpecifyEntryTmpl" Map "Spec" $.Spec "Version" $version.Minimum }}
- {{- end}}
-
- {{- template "NormalizeTmpl" Map "Spec" $.Spec "Version" nil }}
- {{- range $version := .SupportedVersionRanges }}
- {{- template "NormalizeTmpl" Map "Spec" $.Spec "Version" $version.Minimum }}
- {{- end}}
-
- func SpecMatches(a, b *Entry) bool {
- if a == nil && b != nil || a != nil && b == nil {
- return false
- } else if a == nil && b == nil {
- return true
- }
-
- // Don't compare Name.
- {{- range $_, $param := .Spec.SortedParams}}
- if !{{specMatchesFunction $param}}(a.{{$param.Name.CamelCase}}, b.{{$param.Name.CamelCase}}) {
- return false
- }
- {{- end}}
- {{- range $_, $param := .Spec.SortedOneOf}}
- if !{{specMatchesFunction $param}}(a.{{$param.Name.CamelCase}}, b.{{$param.Name.CamelCase}}) {
- return false
- }
- {{- end}}
-
- return true
- }
-
- {{nestedSpecMatchesFunction $.Spec}}
+ {{- RenderSpecMatchers $ }}
func (o *Entry) EntryName() string {
return o.Name
diff --git a/templates/sdk/location.tmpl b/templates/sdk/location.tmpl
index 0c8a9370..196424d6 100644
--- a/templates/sdk/location.tmpl
+++ b/templates/sdk/location.tmpl
@@ -74,7 +74,7 @@ switch {
ans = []string{
{{- range $name, $xpath := $location.Xpath}}
{{- if contains $xpath "Entry"}}
- {{generateEntryXpath "util.AsEntryXpath([]string{" "})" $location.Name.CamelCase $xpath}}
+ {{generateEntryXpath "util.AsEntryXpath(" ")" $location.Name.CamelCase $xpath}}
{{- else if contains $xpath "Object"}}
{{generateEntryXpath "" "" $location.Name.CamelCase $xpath}}
{{- else}}
@@ -90,35 +90,21 @@ return nil, errors.NoLocationSpecifiedError
return ans, nil
}
-{{- if .Entry}}
- func (o Location) XpathWithEntryName(vn version.Number, name string) ([]string, error) {
-{{- else}}
- func (o Location) Xpath(vn version.Number) ([]string, error) {
-{{- end}}
-
-ans, err := o.XpathPrefix(vn)
-if err != nil {
-return nil, err
-}
+func (o Location) XpathWithComponents(vn version.Number, components ...string) ([]string, error) {
+ if len(components) != {{ .ResourceXpathVariablesCount }} {
+ return nil, fmt.Errorf("invalid number of arguments for XpathWithComponents() call")
+ }
-{{- if .Entry}}
- ans = append(ans, Suffix...)
- ans = append(ans, util.AsEntryXpath([]string{name}))
-{{- end}}
+ {{ .ResourceXpathVariableChecks }}
-return ans, nil
-}
+ ans, err := o.XpathPrefix(vn)
+ if err != nil {
+ return nil, err
+ }
-{{- if .Entry}}
- func (o Location) XpathWithUuid(vn version.Number, uuid string) ([]string, error) {
+ {{- if ge .ResourceXpathVariablesCount 1 }}
+ {{ .ResourceXpathAssignments }}
+ {{- end }}
- ans, err := o.XpathPrefix(vn)
- if err != nil {
- return nil, err
- }
- ans = append(ans, Suffix...)
- ans = append(ans, util.AsUuidXpath(uuid))
-
- return ans, nil
- }
-{{- end}}
+ return ans, nil
+}
diff --git a/templates/sdk/service.tmpl b/templates/sdk/service.tmpl
index 954cfd41..89808bd3 100644
--- a/templates/sdk/service.tmpl
+++ b/templates/sdk/service.tmpl
@@ -55,73 +55,91 @@ client: client,
}
// Create adds new item, then returns the result.
-{{- if and (.Entry) (.Imports)}}
- func (s *Service) Create(ctx context.Context, loc Location, importLocations []ImportLocation, entry *Entry) (*Entry, error) {
-{{- else if (.Entry) }}
- func (s *Service) Create(ctx context.Context, loc Location, entry *Entry) (*Entry, error) {
-{{- else }}
- func (s *Service) Create(ctx context.Context, loc Location, config *Config) (*Config, error) {
-{{- end}}
+ {{- if and (.Entry) (.Imports)}}
+func (s *Service) Create(ctx context.Context, loc Location, importLocations []ImportLocation, entry *Entry) (*Entry, error) {
+ {{- else if (.Entry) }}
+func (s *Service) Create(ctx context.Context, loc Location, entry *Entry) (*Entry, error) {
+ {{- else }}
+func (s *Service) Create(ctx context.Context, loc Location, config *Config) (*Config, error) {
+ {{- end}}
-{{- if .Entry}}
- if entry.Name == "" {
- return nil, errors.NameNotSpecifiedError
- }
-{{- end}}
+ {{- if .Entry}}
+ if entry.Name == "" {
+ return nil, errors.NameNotSpecifiedError
+ }
+ {{- end}}
-vn := s.client.Versioning()
+ vn := s.client.Versioning()
-specifier, _, err := Versioning(vn)
-if err != nil {
-return nil, err
-}
+ {{- if .Entry}}
+ path, err := loc.XpathWithComponents(vn, util.AsEntryXpath(entry.Name))
+ {{- else}}
+ path, err := loc.XpathWithComponents(vn)
+ {{- end}}
+ if err != nil {
+ return nil, err
+ }
-{{- if .Entry}}
- path, err := loc.XpathWithEntryName(vn, entry.Name)
-{{- else}}
- path, err := loc.Xpath(vn)
-{{- end}}
-if err != nil {
-return nil, err
-}
+ {{- if .Entry}}
+ err = s.CreateWithXpath(ctx, util.AsXpath(path[:len(path)-1]), entry)
+ {{- else}}
+ err = s.CreateWithXpath(ctx, util.AsXpath(path[:len(path)-1]), config)
+ {{- end}}
+ if err != nil {
+ return nil, err
+ }
-{{- if .Entry}}
- createSpec, err := specifier(entry)
-{{- else}}
- createSpec, err := specifier(config)
-{{- end}}
-if err != nil {
-return nil, err
-}
+ {{- if .Imports }}
+ err = s.ImportToLocations(ctx, loc, importLocations, entry.Name)
+ if err != nil {
+ return nil, err
+ }
+ {{- end }}
-cmd := &xmlapi.Config{
-Action: "set",
-Xpath: util.AsXpath(path[:len(path)-1]),
-Element: createSpec,
-Target: s.client.GetTarget(),
+ return s.ReadWithXpath(ctx, util.AsXpath(path), "get")
}
-if _, _, err = s.client.Communicate(ctx, cmd, false, nil); err != nil {
-return nil, err
-}
-{{- if .Imports }}
-err = s.importToLocations(ctx, loc, importLocations, entry.Name)
-if err != nil {
- return nil, err
-}
-{{- end }}
+ {{ $funcDef := "" }}
+ {{- if .Entry }}
+ {{ $funcDef = "CreateWithXpath(ctx context.Context, xpath string, entry *Entry) error" }}
+ {{- else }}
+ {{ $funcDef = "CreateWithXpath(ctx context.Context, xpath string, config *Config) error" }}
+ {{- end }}
-{{- if .Entry}}
- return s.Read(ctx, loc, entry.Name, "get")
-{{- else}}
- return s.Read(ctx, loc, "get")
-{{- end}}
+func (s *Service) {{ $funcDef }} {
+ vn := s.client.Versioning()
+ specifier, _, err := Versioning(vn)
+ if err != nil {
+ return err
+ }
+
+ {{- if .Entry}}
+ createSpec, err := specifier(entry)
+ {{- else}}
+ createSpec, err := specifier(config)
+ {{- end}}
+ if err != nil {
+ return err
+ }
+
+ cmd := &xmlapi.Config{
+ Action: "set",
+ Xpath: xpath,
+ Element: createSpec,
+ Target: s.client.GetTarget(),
+ }
+
+ if _, _, err = s.client.Communicate(ctx, cmd, false, nil); err != nil {
+ return err
+ }
+
+ return nil
}
{{- if .Imports }}
-func (s *Service) importToLocations(ctx context.Context, loc Location, importLocations []ImportLocation, entryName string) error {
+func (s *Service) ImportToLocations(ctx context.Context, loc Location, importLocations []ImportLocation, entryName string) error {
vn := s.client.Versioning()
importToLocation := func(il ImportLocation) error {
@@ -186,7 +204,7 @@ func (s *Service) importToLocations(ctx context.Context, loc Location, importLoc
return nil
}
-func (s *Service) unimportFromLocations(ctx context.Context, loc Location, importLocations []ImportLocation, values []string) error {
+func (s *Service) UnimportFromLocations(ctx context.Context, loc Location, importLocations []ImportLocation, values []string) error {
vn := s.client.Versioning()
valuesByName := make(map[string]bool)
for _, elt := range values {
@@ -259,115 +277,96 @@ func (s *Service) unimportFromLocations(ctx context.Context, loc Location, impor
{{- if .Entry}}
func (s *Service) Read(ctx context.Context, loc Location, name, action string) (*Entry, error) {
{{- if $.Spec.Params.uuid}}
- return s.read(ctx, loc, name, action, true, false)
+ return s.read(ctx, loc, name, action, true)
{{- else}}
- return s.read(ctx, loc, name, action, false)
+ return s.read(ctx, loc, name, action)
{{- end}}
}
{{- if $.Spec.Params.uuid}}
// ReadById returns the given config object with specified ID, using the specified action ("get" or "show").
func (s *Service) ReadById(ctx context.Context, loc Location, uuid, action string) (*Entry, error) {
- return s.read(ctx, loc, uuid, action, false, false)
+ return s.read(ctx, loc, uuid, action, false)
}
{{- end}}
{{- else}}
func (s *Service) Read(ctx context.Context, loc Location, action string) (*Config, error) {
- return s.read(ctx, loc, action, false)
+ return s.read(ctx, loc, action)
}
{{- end}}
-// ReadFromConfig returns the given config object from the loaded XML config.
-// Requires that client.LoadPanosConfig() has been invoked.
-{{- if .Entry}}
- func (s *Service) ReadFromConfig(ctx context.Context, loc Location, name string) (*Entry, error) {
- {{- if $.Spec.Params.uuid}}
- return s.read(ctx, loc, name, "", true, true)
- {{- else}}
- return s.read(ctx, loc, name, "", true)
- {{- end}}
- }
- {{- if $.Spec.Params.uuid}}
- // ReadFromConfigById returns the given config object with specified ID from the loaded XML config.
- // Requires that client.LoadPanosConfig() has been invoked.
- func (s *Service) ReadFromConfigById(ctx context.Context, loc Location, uuid string) (*Entry, error) {
- return s.read(ctx, loc, uuid, "", false, true)
- }
- {{- end}}
-{{- else}}
- func (s *Service) ReadFromConfig(ctx context.Context, loc Location) (*Config, error) {
- return s.read(ctx, loc, "", true)
- }
-{{- end}}
+ {{ $funcDef := "" }}
+ {{- if .Entry }}
+ {{ $funcDef = "ReadWithXpath(ctx context.Context, xpath string, action string) (*Entry, error)" }}
+ {{- else }}
+ {{ $funcDef = "ReadWithXpath(ctx context.Context, xpath string, action string) (*Config, error)" }}
+ {{- end }}
+func (s *Service) {{ $funcDef }} {
+ vn := s.client.Versioning()
+ _, normalizer, err := Versioning(vn)
+ if err != nil {
+ return nil, err
+ }
+
+ cmd := &xmlapi.Config{
+ Action: action,
+ Xpath: xpath,
+ Target: s.client.GetTarget(),
+ }
+
+ if _, _, err = s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
+ if err.Error() == "No such node" && action == "show" {
+ return nil, errors.ObjectNotFound()
+ }
+ return nil, err
+ }
+
+ list, err := normalizer.Normalize()
+ if err != nil {
+ return nil, err
+ } else if len(list) != 1 {
+ return nil, fmt.Errorf("expected to %q 1 entry, got %d", action, len(list))
+ }
-{{if .Entry}}
+ return list[0], nil
+}
+
+ {{if .Entry}}
{{- if $.Spec.Params.uuid}}
- func (s *Service) read(ctx context.Context, loc Location, value, action string, byName, usePanosConfig bool) (*Entry, error) {
+func (s *Service) read(ctx context.Context, loc Location, value, action string, byName bool) (*Entry, error) {
if byName && value == "" {
- return nil, errors.NameNotSpecifiedError
- }
- if !byName && value == "" {
- return nil, errors.UuidNotSpecifiedError
+ return nil, errors.NameNotSpecifiedError
}
+
+ if !byName && value == "" {
+ return nil, errors.UuidNotSpecifiedError
+ }
{{- else}}
- func (s *Service) read(ctx context.Context, loc Location, value, action string, usePanosConfig bool) (*Entry, error) {
+func (s *Service) read(ctx context.Context, loc Location, value, action string) (*Entry, error) {
if value == "" {
return nil, errors.NameNotSpecifiedError
}
{{- end}}
-{{- else}}
- func (s *Service) read(ctx context.Context, loc Location, action string, usePanosConfig bool) (*Config, error) {
-{{- end}}
-vn := s.client.Versioning()
-_, normalizer, err := Versioning(vn)
-if err != nil {
-return nil, err
-}
+ {{- else}}
+func (s *Service) read(ctx context.Context, loc Location, action string) (*Config, error) {
+ {{- end}}
+ vn := s.client.Versioning()
-{{- if .Entry}}
- var path []string
+ {{- if .Entry}}
+ var path []string
+ var err error
{{- if $.Spec.Params.uuid}}
- if byName {
- path, err = loc.XpathWithEntryName(vn, value)
- } else {
- path, err = loc.XpathWithUuid(vn, value)
- }
+ path, err = loc.XpathWithComponents(vn, value)
{{- else}}
- path, err = loc.XpathWithEntryName(vn, value)
+ path, err = loc.XpathWithComponents(vn, value)
{{- end}}
-{{- else}}
- path, err := loc.Xpath(vn)
-{{- end}}
-if err != nil {
-return nil, err
-}
-
-if usePanosConfig {
-if _, err = s.client.ReadFromConfig(ctx, path, true, normalizer); err != nil {
-return nil, err
-}
-} else {
-cmd := &xmlapi.Config{
-Action: action,
-Xpath: util.AsXpath(path),
-Target: s.client.GetTarget(),
-}
-
-if _, _, err = s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
-if err.Error() == "No such node" && action == "show" {
-return nil, errors.ObjectNotFound()
-}
-return nil, err
-}
-}
-
-list, err := normalizer.Normalize()
-if err != nil {
-return nil, err
-} else if len(list) != 1 {
-return nil, fmt.Errorf("expected to %q 1 entry, got %d", action, len(list))
-}
+ {{- else}}
+ path, err := loc.XpathWithComponents(vn)
+ {{- end}}
+ if err != nil {
+ return nil, err
+ }
-return list[0], nil
+ return s.ReadWithXpath(ctx, util.AsXpath(path), action)
}
{{ $object := "Config" }}
@@ -376,138 +375,127 @@ return list[0], nil
{{- end }}
{{- if .Entry }}
- // Update updates the given config object, then returns the result.
- func (s *Service) Update(ctx context.Context, loc Location, entry *{{ $object }}, name string) (*{{ $object }}, error) {
- {{- if $.Spec.Params.uuid}}
- return s.update(ctx, loc, entry, name, true)
- {{- else}}
- return s.update(ctx, loc, entry, name)
- {{- end}}
- }
+func (s *Service) Update(ctx context.Context, loc Location, entry *{{ $object }}, name string) (*{{ $object }}, error) {
+ if entry.Name == "" {
+ return nil, errors.NameNotSpecifiedError
+ }
- {{- if $.Spec.Params.uuid}}
- // UpdateById updates the given config object, then returns the result.
- func (s *Service) UpdateById(ctx context.Context, loc Location, entry *{{ $object }}, uuid string) (*{{ $object }}, error) {
- return s.update(ctx, loc, entry, uuid, false)
- }
- {{- end}}
+ xpath, err := loc.XpathWithComponents(s.client.Versioning(), entry.Name)
+ if err != nil {
+ return nil, err
+ }
- {{- if $.Spec.Params.uuid}}
- func (s *Service) update(ctx context.Context, loc Location, entry *{{ $object }}, value string, byName bool) (*{{ $object }}, error) {
- {{- if .Entry }}
- if byName && entry.Name == "" {
- return nil, errors.NameNotSpecifiedError
- }
- if !byName && value == "" {
- return nil, errors.UuidNotSpecifiedError
- }
- {{- end }}
- {{- else}}
- func (s *Service) update(ctx context.Context, loc Location, entry *{{ $object }}, value string) (*{{ $object }}, error) {
- {{- if .Entry }}
- if entry.Name == "" {
- return nil, errors.NameNotSpecifiedError
- }
- {{- end }}
- {{- end}}
+ err = s.UpdateWithXpath(ctx, util.AsXpath(xpath), entry, name)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
+}
+{{- else }}
+func (s *Service) Update(ctx context.Context, loc Location, entry *{{ $object }}, name string) (*{{ $object }}, error) {
+ xpath, err := loc.XpathWithComponents(s.client.Versioning())
+ if err != nil {
+ return nil, err
+ }
+
+ err = s.UpdateWithXpath(ctx, util.AsXpath(xpath), entry)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.ReadWithXpath(ctx, util.AsXpath(xpath), "get")
+}
+{{- end }}
+
+{{- if .Entry }}
+func (s *Service) UpdateWithXpath(ctx context.Context, xpath string, entry *{{ $object }}, name string) error {
{{- else }}
-func (s *Service) Update(ctx context.Context, loc Location, entry *{{ $object }}) (*{{ $object }}, error) {
+func (s *Service) UpdateWithXpath(ctx context.Context, xpath string, entry *{{ $object }}) error {
{{- end }}
+ vn := s.client.Versioning()
+ updates := xmlapi.NewMultiConfig(2)
+ specifier, _, err := Versioning(vn)
+ if err != nil {
+ return err
+ }
- vn := s.client.Versioning()
- updates := xmlapi.NewMultiConfig(2)
- specifier, _, err := Versioning(vn)
- if err != nil {
- return nil, err
- }
+ var old *{{ $object }}
{{- if .Entry }}
- var old *{{ $object }}
- {{- if $.Spec.Params.uuid}}
- if byName {
- {{- end}}
- if value != "" && value != entry.Name {
- path, err := loc.XpathWithEntryName(vn, value)
- if err != nil {
- return nil, err
- }
+ if name != "" && name != entry.Name {
+ old, err = s.ReadWithXpath(ctx, xpath, "get")
+ if err != nil {
+ return err
+ }
- old, err = s.Read(ctx, loc, value, "get")
+ if old != nil {
+ return errors.ObjectExists
+ }
- updates.Add(&xmlapi.Config{
- Action: "rename",
- Xpath: util.AsXpath(path),
- NewName: entry.Name,
- Target: s.client.GetTarget(),
- })
- } else {
- old, err = s.Read(ctx, loc, entry.Name, "get")
- }
- {{- if $.Spec.Params.uuid}}
- } else {
- old, err = s.ReadById(ctx, loc, value, "get")
- }
- {{- end}}
- if err != nil {
- return nil, err
- } else if old == nil {
- return nil, fmt.Errorf("previous object doesn't exist for update")
- }
- {{- else }}
- var old *{{ $object }}
- old, err = s.Read(ctx, loc, "get")
- if err != nil {
- return nil, err
- } else if old == nil {
- return nil, fmt.Errorf("previous object doesn't exist for update")
- }
- {{- end }}
+ updates.Add(&xmlapi.Config{
+ Action: "rename",
+ Xpath: util.AsXpath(xpath),
+ NewName: entry.Name,
+ Target: s.client.GetTarget(),
+ })
+ } else {
+ old, err = s.ReadWithXpath(ctx, xpath, "get")
+ if err != nil {
+ return err
+ }
- {{- if .Entry }}
- if !SpecMatches(entry, old) {
- path, err := loc.XpathWithEntryName(vn, entry.Name)
- {{- else }}
- if !SpecMatches(entry, old) {
- path, err := loc.Xpath(vn)
- {{- end }}
- if err != nil {
- return nil, err
- }
+ if old == nil {
+ return errors.ObjectNotFound()
+ }
+ if SpecMatches(entry, old) {
+ return nil
+ }
- updateSpec, err := specifier(entry)
+ updateSpec, err := specifier(entry)
+ if err != nil {
+ return err
+ }
+
+ updates.Add(&xmlapi.Config{
+ Action: "edit",
+ Xpath: util.AsXpath(xpath),
+ Element: updateSpec,
+ Target: s.client.GetTarget(),
+ })
+ }
+ {{- else }}
+ old, err = s.ReadWithXpath(ctx, xpath, "get")
if err != nil {
- return nil, err
- }
+ return err
+ }
- updates.Add(&xmlapi.Config{
- Action: "edit",
- Xpath: util.AsXpath(path),
- Element: updateSpec,
- Target: s.client.GetTarget(),
- })
- }
+ if SpecMatches(entry, old) {
+ return nil
+ }
- if len(updates.Operations) != 0 {
- if _, _, _, err = s.client.MultiConfig(ctx, updates, false, nil); err != nil {
- return nil, err
- }
- }
+ updateSpec, err := specifier(entry)
+ if err != nil {
+ return err
+ }
- {{- if .Entry }}
- {{- if $.Spec.Params.uuid}}
- if byName {
- return s.Read(ctx, loc, entry.Name, "get")
- } else {
- return s.ReadById(ctx, loc, value, "get")
- }
- {{- else}}
- return s.Read(ctx, loc, entry.Name, "get")
- {{- end}}
- {{- else }}
- return s.Read(ctx, loc, "get")
+ updates.Add(&xmlapi.Config{
+ Action: "edit",
+ Xpath: util.AsXpath(xpath),
+ Element: updateSpec,
+ Target: s.client.GetTarget(),
+ })
{{- end }}
+
+ if len(updates.Operations) != 0 {
+ if _, _, _, err = s.client.MultiConfig(ctx, updates, false, nil); err != nil {
+ return err
+ }
+ }
+
+ return nil
}
// Delete deletes the given item.
@@ -585,24 +573,16 @@ vn := s.client.Versioning()
var err error
deletes := xmlapi.NewMultiConfig(len(values))
{{- if .Imports }}
- err = s.unimportFromLocations(ctx, loc, importLocations, values)
+ err = s.UnimportFromLocations(ctx, loc, importLocations, values)
if err != nil {
return err
}
{{- end }}
for _, value := range values {
var path []string
- {{- if $.Spec.Params.uuid}}
- if byName {
- path, err = loc.XpathWithEntryName(vn, value)
- } else {
- path, err = loc.XpathWithUuid(vn, value)
- }
- {{- else}}
- path, err = loc.XpathWithEntryName(vn, value)
- {{- end}}
+ path, err = loc.XpathWithComponents(vn, util.AsEntryXpath(value))
{{- else}}
- path, err := loc.Xpath(vn)
+ path, err := loc.XpathWithComponents(vn)
{{- end}}
if err != nil {
return err
@@ -725,85 +705,75 @@ func (s *Service) RemoveFromImport(ctx context.Context, loc Location, entry Entr
{{- end}}
{{- if .Entry}}
- // List returns a list of objects using the given action ("get" or "show").
- // Params filter and quote are for client side filtering.
- func (s *Service) List(ctx context.Context, loc Location, action, filter, quote string) ([]*Entry, error) {
- return s.list(ctx, loc, action, filter, quote, false)
- }
-
- // ListFromConfig returns a list of objects at the given location.
- // Requires that client.LoadPanosConfig() has been invoked.
- // Params filter and quote are for client side filtering.
- func (s *Service) ListFromConfig(ctx context.Context, loc Location, filter, quote string) ([]*Entry, error) {
- return s.list(ctx, loc, "", filter, quote, true)
- }
-
- func (s *Service) list(ctx context.Context, loc Location, action, filter, quote string, usePanosConfig bool) ([]*Entry, error) {
- var err error
+// List returns a list of objects using the given action ("get" or "show").
+// Params filter and quote are for client side filtering.
+func (s *Service) List(ctx context.Context, loc Location, action, filter, quote string) ([]*Entry, error) {
+ return s.list(ctx, loc, action, filter, quote)
+}
- var logic *filtering.Group
- if filter != "" {
- logic, err = filtering.Parse(filter, quote)
- if err != nil {
- return nil, err
- }
- }
+func (s *Service) list(ctx context.Context, loc Location, action, filter, quote string) ([]*Entry, error) {
+ xpath, err := loc.XpathWithComponents(s.client.Versioning(), util.AsEntryXpath(""))
+ if err != nil {
+ return nil, err
+ }
- vn := s.client.Versioning()
+ return s.ListWithXpath(ctx, util.AsXpath(xpath), action, filter, quote)
+}
- _, normalizer, err := Versioning(vn)
- if err != nil {
- return nil, err
- }
+func (s *Service) ListWithXpath(ctx context.Context, xpath string, action, filter, quote string) ([]*Entry, error) {
+ var logic *filtering.Group
+ if filter != "" {
+ var err error
+ logic, err = filtering.Parse(filter, quote)
+ if err != nil {
+ return nil, err
+ }
+ }
- path, err := loc.XpathWithEntryName(vn, "")
- if err != nil {
- return nil, err
- }
+ vn := s.client.Versioning()
- if usePanosConfig {
- if _, err = s.client.ReadFromConfig(ctx, path, false, normalizer); err != nil {
- return nil, err
- }
- } else{
- cmd := &xmlapi.Config{
- Action: action,
- Xpath: util.AsXpath(path),
- Target: s.client.GetTarget(),
- }
+ _, normalizer, err := Versioning(vn)
+ if err != nil {
+ return nil, err
+ }
- if _, _, err = s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
- if err.Error() == "No such node" && action == "show" {
- return nil, nil
- }
- return nil, err
- }
- }
+ cmd := &xmlapi.Config{
+ Action: action,
+ Xpath: util.AsXpath(xpath),
+ Target: s.client.GetTarget(),
+ }
- listing, err := normalizer.Normalize()
- if err != nil || logic == nil {
- return listing, err
- }
+ if _, _, err = s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
+ if err.Error() == "No such node" && action == "show" {
+ return nil, nil
+ }
+ return nil, err
+ }
- filtered := make([]*Entry, 0, len(listing))
- for _, x := range listing {
- ok, err := logic.Matches(x)
- if err != nil {
- return nil, err
- }
- if ok {
- filtered = append(filtered, x)
- }
- }
+ listing, err := normalizer.Normalize()
+ if err != nil || logic == nil {
+ return listing, err
+ }
- return filtered, nil
- }
+ filtered := make([]*Entry, 0, len(listing))
+ for _, x := range listing {
+ ok, err := logic.Matches(x)
+ if err != nil {
+ return nil, err
+ }
+ if ok {
+ filtered = append(filtered, x)
+ }
+ }
+
+ return filtered, nil
+}
- {{- if $.Spec.Params.uuid}}
- // MoveGroup arranges the given rules in the order specified.
- // Any rule with a UUID specified is ignored.
- // Only the rule names are considered for the purposes of the rule placement.
- func (s *Service) MoveGroup(ctx context.Context, loc Location, position movement.Position, entries []*Entry, batchSize int) error {
+{{- if $.Spec.Params.uuid}}
+// MoveGroup arranges the given rules in the order specified.
+// Any rule with a UUID specified is ignored.
+// Only the rule names are considered for the purposes of the rule placement.
+func (s *Service) MoveGroup(ctx context.Context, loc Location, position movement.Position, entries []*Entry, batchSize int) error {
if len(entries) == 0 {
return nil
}
@@ -823,7 +793,7 @@ func (s *Service) RemoveFromImport(ctx context.Context, loc Location, entry Entr
updates := xmlapi.NewChunkedMultiConfig(len(movements), batchSize)
for _, elt := range movements {
- path, err := loc.XpathWithEntryName(s.client.Versioning(), elt.Movable.EntryName())
+ path, err := loc.XpathWithComponents(s.client.Versioning(), util.AsEntryXpath(elt.Movable.EntryName()))
if err != nil {
return err
}
@@ -886,7 +856,7 @@ func (s *Service) RemoveFromImport(ctx context.Context, loc Location, entry Entr
vn := s.client.Versioning()
- path, err := loc.XpathWithEntryName(vn, name)
+ path, err := loc.XpathWithComponents(vn, name)
if err != nil {
return err
}
@@ -911,7 +881,7 @@ func (s *Service) RemoveFromImport(ctx context.Context, loc Location, entry Entr
vn := s.client.Versioning()
- path, err := loc.XpathWithEntryName(vn, name)
+ path, err := loc.XpathWithComponents(vn, name)
if err != nil {
return "", err
}