func (p *PaloAlto) AddressGroups(devicegroup ...string) (*AddressGroups, error) {
	var parsedGroups xmlAddressGroups
	var groups AddressGroups
	xpath := "/config//address-group"
	if p.DeviceType == "panos" {
		if p.Panorama == true {
			xpath = "/config//address-group"
		}
		if p.Panorama == false {
			xpath = "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/address-group"
		}
		if len(devicegroup) > 0 && len(devicegroup[0]) > 0 {
			return nil, errors.New("you must be connected to a Panorama device when specifying a device-group")
		}
	}
	if p.DeviceType == "panorama" {
		if len(devicegroup) > 0 && len(devicegroup[0]) > 0 {
			xpath = fmt.Sprintf("/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='%s']/address-group", devicegroup[0])
		}
	}
	_, groupData, errs := r.Get(p.URI).Query(fmt.Sprintf("type=config&action=get&xpath=%s&key=%s", xpath, p.Key)).End()
	if errs != nil {
		return nil, errs[0]
	}
	if err := xml.Unmarshal([]byte(groupData), &parsedGroups); err != nil {
		return nil, err
	}
	if parsedGroups.Status != "success" {
		return nil, fmt.Errorf("error code %s: %s", parsedGroups.Code, errorCodes[parsedGroups.Code])
	}
	for _, g := range parsedGroups.Groups {
		gname := g.Name
		gtype := "Static"
		gmembers := g.Members
		gfilter := strings.TrimSpace(g.DynamicFilter)
		gdesc := g.Description
		gtag := g.Tag
		if g.DynamicFilter != "" {
			gtype = "Dynamic"
		}
		groups.Groups = append(groups.Groups, AddressGroup{Name: gname, Type: gtype, Members: gmembers, DynamicFilter: gfilter, Description: gdesc, Tag: gtag})
	}
	return &groups, nil
}
AddressGroups returns information about all of the address groups. You can (optionally) specify a device-group
when ran against a Panorama device. If no device-group is specified, then all address groups are returned, including
shared objects if run against a Panorama device.
package panos
import (
	"encoding/xml"
	"errors"
	"fmt"
	"strings"
)
type AddressObjects struct {
	XMLName   xml.Name  `xml:"response"`
	Status    string    `xml:"status,attr"`
	Code      string    `xml:"code,attr"`
	Addresses []Address `xml:"result>address>entry"`
}
type Address struct {
	Name        string   `xml:"name,attr"`
	IPAddress   string   `xml:"ip-netmask,omitempty"`
	IPRange     string   `xml:"ip-range,omitempty"`
	FQDN        string   `xml:"fqdn,omitempty"`
	Description string   `xml:"description,omitempty"`
	Tag         []string `xml:"tag>member,omitempty"`
}
type AddressGroups struct {
	Groups []AddressGroup
}
type AddressGroup struct {
	Name          string
	Type          string
	Members       []string
	DynamicFilter string
	Description   string
	Tag           []string
}
type xmlAddressGroups struct {
	XMLName xml.Name          `xml:"response"`
	Status  string            `xml:"status,attr"`
	Code    string            `xml:"code,attr"`
	Groups  []xmlAddressGroup `xml:"result>address-group>entry"`
}
type xmlAddressGroup struct {
	Name          string   `xml:"name,attr"`
	Members       []string `xml:"static>member,omitempty"`
	DynamicFilter string   `xml:"dynamic>filter,omitempty"`
	Description   string   `xml:"description,omitempty"`
	Tag           []string `xml:"tag>member,omitempty"`
}
func (p *PaloAlto) Addresses(devicegroup ...string) (*AddressObjects, error) {
	var addrs AddressObjects
	xpath := "/config//address"
	if p.DeviceType == "panos" {
		if p.Panorama == true {
			xpath = "/config//address"
		}
		if p.Panorama == false {
			xpath = "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/address"
		}
		if len(devicegroup) > 0 && len(devicegroup[0]) > 0 {
			return nil, errors.New("you must be connected to a Panorama device when specifying a device-group")
		}
	}
	if p.DeviceType == "panorama" {
		if len(devicegroup) > 0 && len(devicegroup[0]) > 0 {
			xpath = fmt.Sprintf("/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='%s']/address", devicegroup[0])
		}
	}
	_, addrData, errs := r.Get(p.URI).Query(fmt.Sprintf("type=config&action=get&xpath=%s&key=%s", xpath, p.Key)).End()
	if errs != nil {
		return nil, errs[0]
	}
	if err := xml.Unmarshal([]byte(addrData), &addrs); err != nil {
		return nil, err
	}
	if addrs.Status != "success" {
		return nil, fmt.Errorf("error code %s: %s", addrs.Code, errorCodes[addrs.Code])
	}
	return &addrs, nil
}