diff --git a/client.go b/client.go
index 6a200d3a..04884783 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
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)
+ }
+}