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", + "", + "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) + } +}