func (v *VxlanInterfaceEntity) parseMulticastGroup(config string) string {
	re := regexp.MustCompile(`vxlan multicast-group ([^\s]+)`)
	match := re.FindStringSubmatch(config)
	if match == nil {
		return ""
	}
	return match[1]
}
parseMulticastGroup parses given vxlan interface config and returns the
multicast group associated with it or empty string if not found.
package module
import (
	"regexp"
	"strconv"
	"strings"
	"github.com/aristanetworks/goeapi"
)
var validInterfaces = map[string]bool{
	"Ethernet":     true,
	"Management":   true,
	"Loopback":     true,
	"Vlan":         true,
	"Port-Channel": true,
	"Vxlan":        true,
}
type InterfaceConfig map[string]string
type BaseInterfaceEntity struct {
	*AbstractBaseEntity
}
func Interface(node *goeapi.Node) *BaseInterfaceEntity {
	return &BaseInterfaceEntity{&AbstractBaseEntity{node}}
}
func isValidInterface(value string) bool {
	var validIntf = regexp.MustCompile(`([EPVLM][a-z-C]+)`)
	match := validIntf.FindString(value)
	if match == "" {
		return false
	}
	_, found := validInterfaces[match]
	return found
}
func (i *BaseInterfaceEntity) Get(name string) InterfaceConfig {
	parent := `interface\s+` + name
	config, _ := i.GetBlock(parent)
	return InterfaceConfig{
		"name":        name,
		"type":        "generic",
		"shutdown":    strconv.FormatBool(i.parseShutdown(config)),
		"description": i.parseDescription(config),
	}
}
func (i *BaseInterfaceEntity) parseShutdown(config string) bool {
	matched, _ := regexp.MatchString(`(?m)no shutdown`, config)
	return !matched
}
func (i *BaseInterfaceEntity) parseDescription(config string) string {
	re := regexp.MustCompile(`(?m)description (.+)$`)
	match := re.FindStringSubmatch(config)
	if match == nil {
		return ""
	}
	return match[1]
}
func (i *BaseInterfaceEntity) Create(name string) bool {
	return i.Configure("interface " + name)
}
func (i *BaseInterfaceEntity) Delete(name string) bool {
	return i.Configure("no interface " + name)
}
func (i *BaseInterfaceEntity) Default(name string) bool {
	return i.Configure("default interface " + name)
}
func (i *BaseInterfaceEntity) SetDescription(name string, value string) bool {
	cmd := i.CommandBuilder("description", value, false, true)
	return i.ConfigureInterface(name, cmd)
}
func (i *BaseInterfaceEntity) SetDescriptionDefault(name string) bool {
	cmd := i.CommandBuilder("description", "", true, false)
	return i.ConfigureInterface(name, cmd)
}
func (i *BaseInterfaceEntity) SetShutdown(name string, shut bool) bool {
	cmd := i.CommandBuilder("shutdown", "", false, shut)
	return i.ConfigureInterface(name, cmd)
}
func (i *BaseInterfaceEntity) SetShutdownDefault(name string) bool {
	cmd := i.CommandBuilder("shutdown", "", true, false)
	return i.ConfigureInterface(name, cmd)
}
type EthernetInterfaceEntity struct {
	*BaseInterfaceEntity
}
func EthernetInterface(node *goeapi.Node) *EthernetInterfaceEntity {
	return &EthernetInterfaceEntity{&BaseInterfaceEntity{&AbstractBaseEntity{node}}}
}
func (e *EthernetInterfaceEntity) Get(name string) InterfaceConfig {
	parent := `interface\s+` + name
	config, _ := e.GetBlock(parent)
	resource := e.BaseInterfaceEntity.Get(name)
	resource["type"] = "ethernet"
	resource["sflow"] = strconv.FormatBool(parseSflow(config))
	resource["flowcontrol_send"] = parseFlowControlSend(config)
	resource["flowcontrol_receive"] = parseFlowControlReceive(config)
	return resource
}
func parseSflow(config string) bool {
	matched, _ := regexp.MatchString("no sflow", config)
	return !matched
}
func parseFlowControlSend(config string) string {
	re := regexp.MustCompile(`(?m)flowcontrol send (\w+)$`)
	match := re.FindStringSubmatch(config)
	if match == nil {
		return "off"
	}
	return match[1]
}
func parseFlowControlReceive(config string) string {
	re := regexp.MustCompile(`(?m)flowcontrol receive (\w+)$`)
	match := re.FindStringSubmatch(config)
	if match == nil {
		return "off"
	}
	return match[1]
}
func (e *EthernetInterfaceEntity) Create(name string) bool {
	return false  
}
func (e *EthernetInterfaceEntity) Delete(name string) bool {
	return false  
}
func (e *EthernetInterfaceEntity) SetFlowcontrolSend(name string, value bool) bool {
	return e.setFlowcontrol(name, "send", value)
}
func (e *EthernetInterfaceEntity) SetFlowcontrolReceive(name string, value bool) bool {
	return e.setFlowcontrol(name, "receive", value)
}
func (e *EthernetInterfaceEntity) setFlowcontrol(name string, direction string, value bool) bool {
	var str string
	if value {
		str = "flowcontrol " + direction + " on"
	} else {
		str = "flowcontrol " + direction + " off"
	}
	cmds := []string{
		"interface " + name,
		str,
	}
	return e.Configure(cmds...)
}
func (e *EthernetInterfaceEntity) DisableFlowcontrolSend(name string) bool {
	return e.disableFlowcontrol(name, "send")
}
func (e *EthernetInterfaceEntity) DisableFlowcontrolReceive(name string) bool {
	return e.disableFlowcontrol(name, "receive")
}
func (e *EthernetInterfaceEntity) disableFlowcontrol(name string, direction string) bool {
	cmds := []string{
		"interface " + name,
		"no flowcontrol " + direction,
	}
	return e.Configure(cmds...)
}
func (e *EthernetInterfaceEntity) SetSflow(name string, value bool) bool {
	str := "no sflow enable"
	if value {
		str = "sflow enable"
	}
	cmds := []string{
		"interface " + name,
		str,
	}
	return e.Configure(cmds...)
}
func (e *EthernetInterfaceEntity) SetSflowDefault(name string) bool {
	cmds := []string{
		"interface " + name,
		"default sflow",
	}
	return e.Configure(cmds...)
}
const defaultLacpMode = "on"
type PortChannelInterfaceEntity struct {
	*BaseInterfaceEntity
}
func PortChannel(node *goeapi.Node) *PortChannelInterfaceEntity {
	return &PortChannelInterfaceEntity{&BaseInterfaceEntity{&AbstractBaseEntity{node}}}
}
func (p *PortChannelInterfaceEntity) Get(name string) InterfaceConfig {
	parent := `interface\s+` + name
	config, _ := p.GetBlock(parent)
	resource := p.BaseInterfaceEntity.Get(name)
	resource["type"] = "portchannel"
	resource["lacp_mode"] = p.getLacpMode(name)
	resource["minimum_links"] = p.parseMinimumLinks(config)
	resource["members"] = strings.Join(p.getMembers(name), ",")
	return resource
}
func (p *PortChannelInterfaceEntity) parseMinimumLinks(config string) string {
	re := regexp.MustCompile(`port-channel min-links (\d+)`)
	match := re.FindStringSubmatch(config)
	if match == nil {
		return ""
	}
	return match[1]
}
func (p *PortChannelInterfaceEntity) getLacpMode(name string) string {
	members := p.getMembers(name)
	re := regexp.MustCompile(`channel-group\s\d+\smode\s(.+)`)
	for _, member := range members {
		parent := `interface\s+` + member
		config, _ := p.GetBlock(parent)
		match := re.FindStringSubmatch(config)
		if match == nil {
			return "NaN"
		}
		return match[1]
	}
	return defaultLacpMode
}
func (p *PortChannelInterfaceEntity) getMembers(name string) []string {
	re := regexp.MustCompile(`(\d+)`)
	match := re.FindStringSubmatch(name)
	if match == nil {
		return nil
	}
	grPid := match[1]
	command := []string{"show port-channel " + grPid + " all-ports"}
	config, _ := p.node.Enable(command)
	tmp := config[0]["result"]
	re = regexp.MustCompile(`\bEthernet[\d]*\b`)
	matches := re.FindAllString(tmp, -1)
	if matches == nil {
		return nil
	}
	return matches
}
func (p *PortChannelInterfaceEntity) SetMembers(name string, members ...string) bool {
	re := regexp.MustCompile(`(\d+)$`)
	match := re.FindStringSubmatch(name)
	if match == nil {
		return false
	}
	grpID := match[1]
	currentMembers := p.getMembers(name)
	lacpMode := p.getLacpMode(name)
	var commands []string
	diff := findDiff(currentMembers, members)
	for _, member := range diff {
		commands = append(commands, "interface "+member)
		commands = append(commands, "no channel-group "+grpID)
	}
	diff = findDiff(members, currentMembers)
	for _, member := range diff {
		commands = append(commands, "interface "+member)
		commands = append(commands, "channel-group "+grpID+" mode "+lacpMode)
	}
	return p.Configure(commands...)
}
func (p *PortChannelInterfaceEntity) SetLacpMode(name string, mode string) bool {
	validModes := map[string]bool{
		"on":      true,
		"passive": true,
		"active":  true,
	}
	if _, found := validModes[mode]; !found {
		return false
	}
	re := regexp.MustCompile(`(\d+)$`)
	match := re.FindStringSubmatch(name)
	if match == nil {
		return false
	}
	grpID := match[1]
	var removeCommands []string
	var addCommands []string
	for _, member := range p.getMembers(name) {
		removeCommands = append(removeCommands, "interface "+member)
		removeCommands = append(removeCommands, "no channel-group "+grpID)
		addCommands = append(addCommands, "interface "+member)
		addCommands = append(addCommands, "channel-group "+grpID+" mode "+mode)
	}
	return p.Configure(append(removeCommands, addCommands...)...)
}
func (p *PortChannelInterfaceEntity) SetMinimumLinks(name string, value int) bool {
	if value < 1 || value > 16 {
		return false
	}
	cmd := "port-channel min-links " + strconv.Itoa(value)
	commands := []string{
		"interface " + name,
		cmd,
	}
	return p.Configure(commands...)
}
func (p *PortChannelInterfaceEntity) SetMinimumLinksDefault(name string) bool {
	commands := []string{
		"interface " + name,
		"default port-channel min-links",
	}
	return p.Configure(commands...)
}
type VxlanInterfaceConfig map[string]string
type VxlanConfigCollection map[string]VxlanInterfaceConfig
type VxlanInterfaceEntity struct {
	*BaseInterfaceEntity
}
func Vxlan(node *goeapi.Node) *VxlanInterfaceEntity {
	return &VxlanInterfaceEntity{&BaseInterfaceEntity{&AbstractBaseEntity{node}}}
}
func (v *VxlanInterfaceEntity) Get(name string) InterfaceConfig {
	parent := `interface\s+` + name
	config, _ := v.GetBlock(parent)
	resource := v.BaseInterfaceEntity.Get(name)
	resource["type"] = "vxlan"
	resource["source_interface"] = v.parseSourceInterface(config)
	resource["multicast_group"] = v.parseMulticastGroup(config)
	resource["udp_port"] = v.parseUDPPort(config)
	resource["flood_list"] = v.parseFloodList(config)
	return resource
}
func (v *VxlanInterfaceEntity) parseSourceInterface(config string) string {
	re := regexp.MustCompile(`vxlan source-interface ([^\s]+)`)
	match := re.FindStringSubmatch(config)
	if match == nil {
		return ""
	}
	return match[1]
}