diff --git a/client.go b/client.go
index 6a200d3a..7325a2a0 100644
--- a/client.go
+++ b/client.go
@@ -42,19 +42,19 @@ import (
//
// The bit-wise flags are as follows:
//
-// * LogQuiet: disables all logging
-// * LogAction: action being performed (Set / Edit / Delete functions)
-// * LogQuery: queries being run (Get / Show functions)
-// * LogOp: operation commands (Op functions)
-// * LogUid: User-Id commands (Uid functions)
-// * LogLog: log retrieval commands
-// * LogExport: log export commands
-// * LogXpath: the resultant xpath
-// * LogSend: xml docuemnt being sent
-// * LogReceive: xml responses being received
-// * LogOsxCurl: output an OSX cURL command for the data being sent in
-// * LogCurlWithPersonalData: If doing a curl style logging, then include
-// personal data in the curl command instead of tokens.
+// - LogQuiet: disables all logging
+// - LogAction: action being performed (Set / Edit / Delete functions)
+// - LogQuery: queries being run (Get / Show functions)
+// - LogOp: operation commands (Op functions)
+// - LogUid: User-Id commands (Uid functions)
+// - LogLog: log retrieval commands
+// - LogExport: log export commands
+// - LogXpath: the resultant xpath
+// - LogSend: xml docuemnt being sent
+// - LogReceive: xml responses being received
+// - LogOsxCurl: output an OSX cURL command for the data being sent in
+// - LogCurlWithPersonalData: If doing a curl style logging, then include
+// personal data in the curl command instead of tokens.
const (
LogQuiet = 1 << (iota + 1)
LogAction
@@ -168,10 +168,10 @@ func (c *Client) Plugins() []plugin.Info {
// client's SystemInfo map.
//
// If not specified, the following is assumed:
-// * Protocol: https
-// * Port: (unspecified)
-// * Timeout: 10
-// * Logging: LogAction | LogUid
+// - Protocol: https
+// - Port: (unspecified)
+// - Timeout: 10
+// - Logging: LogAction | LogUid
func (c *Client) Initialize() error {
if len(c.rb) == 0 {
var e error
@@ -318,34 +318,23 @@ func (c *Client) RequestPasswordHash(val string) (string, error) {
// ValidateConfig performs a commit config validation check.
//
-// Setting sync to true means that this function will block until the job
-// finishes.
-//
-//
-// The sleep param is an optional sleep duration to wait between polling for
-// job completion. This param is only used if sync is set to true.
+// # Cmd interface contained a formatted XML string struct which can be used to either marshalled into XML or one of the
+// validate function.
//
// This function returns the job ID and if any errors were encountered.
-func (c *Client) ValidateConfig(sync bool, sleep time.Duration) (uint, error) {
+func (c *Client) ValidateConfig(cmd interface{}) (uint, []byte, error) {
var err error
+ data := url.Values{}
+ data.Set("type", "op")
- c.LogOp("(op) validating config")
- type op_req struct {
- XMLName xml.Name `xml:"validate"`
- Cmd string `xml:"full"`
- }
- job_ans := util.JobResponse{}
- _, err = c.Op(op_req{}, "", nil, &job_ans)
- if err != nil {
- return 0, err
+ if err = addToData("cmd", cmd, true, &data); err != nil {
+ return 0, nil, err
}
- id := job_ans.Id
- if !sync {
- return id, nil
- }
+ ans := util.JobResponse{}
- return id, c.WaitForJob(id, sleep, nil, nil)
+ b, _, err := c.Communicate(data, &ans)
+ return ans.Id, b, err
}
// RevertToRunningConfig discards any changes made and reverts to the last
@@ -356,10 +345,10 @@ func (c *Client) RevertToRunningConfig() error {
return err
}
-// ConfigLocks returns any config locks that are currently in place.
+// ShowConfigLocks returns any config locks that are currently in place.
//
// If vsys is an empty string, then the vsys will default to "shared".
-func (c *Client) ConfigLocks(vsys string) ([]util.Lock, error) {
+func (c *Client) ShowConfigLocks(vsys string) ([]util.Lock, error) {
var err error
var cmd string
ans := configLocks{}
@@ -368,7 +357,7 @@ func (c *Client) ConfigLocks(vsys string) ([]util.Lock, error) {
vsys = "shared"
}
- if c.Version.Gte(version.Number{9, 1, 0, ""}) {
+ if !c.Version.Gte(version.Number{Major: 9, Minor: 1}) {
var tgt string
if vsys == "shared" {
tgt = "all"
@@ -427,10 +416,10 @@ func (c *Client) UnlockConfig(vsys string) error {
return err
}
-// CommitLocks returns any commit locks that are currently in place.
+// ShowCommitLocks returns any commit locks that are currently in place.
//
// If vsys is an empty string, then the vsys will default to "shared".
-func (c *Client) CommitLocks(vsys string) ([]util.Lock, error) {
+func (c *Client) ShowCommitLocks(vsys string) ([]util.Lock, error) {
if vsys == "" {
vsys = "shared"
}
diff --git a/commit/pano.go b/commit/pano.go
index 51437b34..96f340cd 100644
--- a/commit/pano.go
+++ b/commit/pano.go
@@ -2,7 +2,6 @@ package commit
import (
"encoding/xml"
-
"github.com/PaloAltoNetworks/pango/util"
)
@@ -116,6 +115,8 @@ type PanoramaCommitAll struct {
Description string
IncludeTemplate bool
ForceTemplateValues bool
+ ValidateOnly bool
+ Admins []string
Devices []string
}
@@ -139,8 +140,12 @@ func (o PanoramaCommitAll) Element() interface{} {
Description: o.Description,
IncludeTemplate: util.YesNo(o.IncludeTemplate),
ForceTemplateValues: util.YesNo(o.ForceTemplateValues),
+ ValidateOnly: util.YesNo(o.ValidateOnly),
},
}
+ if len(o.Admins) > 0 {
+ ans.DeviceGroup.Admins = util.StrToMem(o.Admins)
+ }
case TypeTemplate:
ans = panoCommitAll{
Template: &pcaTemplate{
@@ -148,8 +153,12 @@ func (o PanoramaCommitAll) Element() interface{} {
Description: o.Description,
ForceTemplateValues: util.YesNo(o.ForceTemplateValues),
Devices: util.StrToMem(o.Devices),
+ ValidateOnly: util.YesNo(o.ValidateOnly),
},
}
+ if len(o.Admins) > 0 {
+ ans.Template.Admins = util.StrToMem(o.Admins)
+ }
case TypeTemplateStack:
ans = panoCommitAll{
TemplateStack: &pcaTemplate{
@@ -157,8 +166,12 @@ func (o PanoramaCommitAll) Element() interface{} {
Description: o.Description,
ForceTemplateValues: util.YesNo(o.ForceTemplateValues),
Devices: util.StrToMem(o.Devices),
+ ValidateOnly: util.YesNo(o.ValidateOnly),
},
}
+ if len(o.Admins) > 0 {
+ ans.TemplateStack.Admins = util.StrToMem(o.Admins)
+ }
case TypeLogCollectorGroup:
ans = panoCommitAll{
LogCollectorGroup: &pcaLogCollectorGroup{
@@ -181,7 +194,6 @@ func (o PanoramaCommitAll) Element() interface{} {
},
}
}
-
return ans
}
@@ -195,10 +207,12 @@ type panoCommitAll struct {
}
type pcaDeviceGroup struct {
- DgInfo pcaDgInfo `xml:"device-group"`
- Description string `xml:"description,omitempty"`
- IncludeTemplate string `xml:"include-template"`
- ForceTemplateValues string `xml:"force-template-values"`
+ DgInfo pcaDgInfo `xml:"device-group"`
+ Admins *util.MemberType `xml:"admin,omitempty"`
+ Description string `xml:"description,omitempty"`
+ IncludeTemplate string `xml:"include-template"`
+ ForceTemplateValues string `xml:"force-template-values"`
+ ValidateOnly string `xml:"validate-only"`
}
type pcaDgInfo struct {
@@ -211,10 +225,12 @@ type pcaDgInfoEntry struct {
}
type pcaTemplate struct {
+ Admins *util.MemberType `xml:"admin,omitempty"`
+ Devices *util.MemberType `xml:"device"`
Name string `xml:"name"`
Description string `xml:"description,omitempty"`
- Devices *util.MemberType `xml:"device"`
ForceTemplateValues string `xml:"force-template-values"`
+ ValidateOnly string `xml:"validate-only"`
}
type pcaLogCollectorGroup struct {
diff --git a/commit/pano_test.go b/commit/pano_test.go
index 523e40ca..c463cdd9 100644
--- a/commit/pano_test.go
+++ b/commit/pano_test.go
@@ -119,6 +119,7 @@ func TestPanoCommitAllDeviceGroup(t *testing.T) {
"device group",
"yes",
"no",
+ "no",
"",
"",
}
@@ -142,10 +143,11 @@ func TestPanoCommitAllTemplate(t *testing.T) {
s := []string{
"",
"",
+ "12321",
"tmpl1",
"template",
- "12321",
"yes",
+ "no",
"",
"",
}
@@ -169,10 +171,11 @@ func TestPanoCommitAllTemplateStack(t *testing.T) {
s := []string{
"",
"",
+ "12321",
"ts1",
"template stack",
- "12321",
"yes",
+ "no",
"",
"",
}
diff --git a/commit/validate.go b/commit/validate.go
new file mode 100644
index 00000000..14eec03a
--- /dev/null
+++ b/commit/validate.go
@@ -0,0 +1,81 @@
+package commit
+
+import (
+ "encoding/xml"
+ "github.com/PaloAltoNetworks/pango/util"
+)
+
+// PanoramaValidate is a Panorama Valid structure contained all option for Client.ValidateConfig().
+type PanoramaValidate struct {
+ Admins []string
+ DeviceGroups []string
+ LogCollectors []string
+ LogCollectorGroups []string
+ Templates []string
+ TemplateStacks []string
+ WildfireAppliances []string
+ WildfireApplianceClusters []string
+ ExcludeDeviceAndNetwork bool
+ ExcludeSharedObjects bool
+ Full bool
+}
+
+// PanoramaValidateAll it is a shell struct for doing validate all changes in Panorama.
+type PanoramaValidateAll struct{}
+
+// Element this function return an interface ready to be marshalled into XML for validate.
+func (o PanoramaValidate) Element() interface{} {
+ ans := panoValidate{}
+
+ var p *panoValidatePartial
+ if len(o.Admins) > 0 || len(o.DeviceGroups) > 0 || len(o.Templates) > 0 ||
+ len(o.TemplateStacks) > 0 || len(o.LogCollectors) > 0 || len(o.LogCollectorGroups) > 0 {
+ p = &panoValidatePartial{
+ Admins: util.StrToMem(o.Admins),
+ DeviceGroups: util.StrToMem(o.DeviceGroups),
+ Templates: util.StrToMem(o.Templates),
+ TemplateStacks: util.StrToMem(o.TemplateStacks),
+ WildfireAppliances: util.StrToMem(o.WildfireAppliances),
+ WildfireClusters: util.StrToMem(o.WildfireApplianceClusters),
+ LogCollectors: util.StrToMem(o.LogCollectors),
+ LogCollectorGroups: util.StrToMem(o.LogCollectorGroups),
+ }
+
+ if o.ExcludeSharedObjects {
+ p.ExcludeSharedObjects = "excluded"
+ }
+
+ if o.ExcludeDeviceAndNetwork {
+ p.ExcludeDeviceAndNetwork = "excluded"
+ }
+ } else {
+ ans.Full = &panoValidateFull{}
+ }
+
+ ans.Partial = p
+
+ return ans
+}
+
+// panoValidate main XML structure for validate, it contains main 'validate' option and regarded for the action
+// it can be either 'full' or 'partial'
+type panoValidate struct {
+ XMLName xml.Name `xml:"validate"`
+ Full *panoValidateFull `xml:"full"`
+ Partial *panoValidatePartial `xml:"partial"`
+}
+
+type panoValidateFull struct{}
+
+type panoValidatePartial struct {
+ Admins *util.MemberType `xml:"admin"`
+ DeviceGroups *util.MemberType `xml:"device-group"`
+ Templates *util.MemberType `xml:"template"`
+ TemplateStacks *util.MemberType `xml:"template-stack"`
+ WildfireAppliances *util.MemberType `xml:"wildfire-appliance"`
+ WildfireClusters *util.MemberType `xml:"wildfire-appliance-cluster"`
+ LogCollectors *util.MemberType `xml:"log-collector"`
+ LogCollectorGroups *util.MemberType `xml:"log-collector-group"`
+ ExcludeDeviceAndNetwork string `xml:"device-and-network,omitempty"`
+ ExcludeSharedObjects string `xml:"shared-object,omitempty"`
+}
diff --git a/commit/validate_test.go b/commit/validate_test.go
new file mode 100644
index 00000000..2d37fec3
--- /dev/null
+++ b/commit/validate_test.go
@@ -0,0 +1,63 @@
+package commit
+
+import (
+ "encoding/xml"
+ "strings"
+ "testing"
+)
+
+func TestPanoramaValidate_ValidateElement(t *testing.T) {
+ testS := []string{
+ "",
+ "",
+ "admin1admin2",
+ "dg1",
+ "tmpl1",
+ "ts1",
+ "wfa1",
+ "wfc1",
+ "lc1",
+ "lcg1",
+ "excluded",
+ "excluded",
+ "",
+ "",
+ }
+
+ expected := strings.Join(testS, "")
+
+ validateStruct := PanoramaValidate{
+ Admins: []string{"admin1", "admin2"},
+ DeviceGroups: []string{"dg1"},
+ LogCollectors: []string{"lc1"},
+ LogCollectorGroups: []string{"lcg1"},
+ Templates: []string{"tmpl1"},
+ TemplateStacks: []string{"ts1"},
+ WildfireAppliances: []string{"wfa1"},
+ WildfireApplianceClusters: []string{"wfc1"},
+ ExcludeDeviceAndNetwork: true,
+ ExcludeSharedObjects: true,
+ }
+
+ marshV, _ := xml.Marshal(validateStruct.Element())
+ if expected != string(marshV) {
+ t.Errorf("Expected(%s) got(%s)", expected, marshV)
+ }
+}
+
+func TestPanoramaValidateAll_ValidateAllElement(t *testing.T) {
+ testS := []string{
+ "",
+ "",
+ "",
+ "",
+ }
+
+ expected := strings.Join(testS, "")
+ validateStruct := PanoramaValidate{}
+
+ marshV, _ := xml.Marshal(validateStruct.Element())
+ if expected != string(marshV) {
+ t.Errorf("Expected(%s) got(%s)", expected, marshV)
+ }
+}